Changes in / [921b84f:5fb32c5] in mainline


Ignore:
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • HelenOS.config

    r921b84f r5fb32c5  
    7070@ "pentium4" Pentium 4
    7171@ "pentium3" Pentium 3
    72 @ "i486" i486
    7372@ "core" Core Solo/Duo
    7473@ "athlon_xp" Athlon XP
    7574@ "athlon_mp" Athlon MP
     75@ "i486" i486
    7676! [PLATFORM=ia32] PROCESSOR (choice)
    7777
  • abi/include/ipc/methods.h

    r921b84f r5fb32c5  
    9696 *                       error is sent back to caller. Otherwise
    9797 *                       the call is accepted and the response is sent back.
    98  *                     - the hash of the client task is passed to userspace
    99  *                       (on the receiving side) as ARG4 of the call.
    10098 *                     - the hash of the allocated phone is passed to userspace
    10199 *                       (on the receiving side) as ARG5 of the call.
  • kernel/arch/ia32/Makefile.inc

    r921b84f r5fb32c5  
    4444#
    4545
     46ifeq ($(PROCESSOR),i486)
     47        CMN2 = -march=i486
     48endif
     49
    4650ifeq ($(PROCESSOR),athlon_xp)
    4751        CMN2 = -march=athlon-xp
     
    6266        CMN2 = -march=pentium4
    6367        SUNCC_CFLAGS += -xarch=sse2
    64 endif
    65 
    66 ifeq ($(PROCESSOR),i486)
    67         CMN2 = -march=i486
    6868endif
    6969
  • kernel/arch/ia32/include/asm.h

    r921b84f r5fb32c5  
    312312
    313313#ifndef PROCESSOR_i486
     314
    314315/** Write to MSR */
    315316NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
     
    336337        return ((uint64_t) dx << 32) | ax;
    337338}
    338 #endif
     339
     340#endif /* PROCESSOR_i486 */
    339341
    340342
  • kernel/arch/ia32/include/boot/boot.h

    r921b84f r5fb32c5  
    4343#define MULTIBOOT_HEADER_FLAGS  0x00010003
    4444
     45#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
     46
    4547#ifndef __ASM__
    4648
  • kernel/arch/ia32/src/asm.S

    r921b84f r5fb32c5  
    407407#ifdef PROCESSOR_i486
    408408        jz 0f
    409         movl %eax, %ebp
    410 0:
     409                movl %eax, %ebp
     410        0:
    411411#else
    412412        cmovnzl %eax, %ebp
  • kernel/arch/ia32/src/boot/boot.S

    r921b84f r5fb32c5  
    9999#include "vesa_prot.inc"
    100100       
    101         /* Map kernel and turn paging on */
    102         call map_kernel
     101#ifndef PROCESSOR_i486
     102       
     103        pm_status $status_prot2
     104       
     105        movl $(INTEL_CPUID_LEVEL), %eax
     106        cpuid
     107        cmp $0x0, %eax  /* any function > 0? */
     108        jbe pse_unsupported
     109       
     110        movl $(INTEL_CPUID_STANDARD), %eax
     111        cpuid
     112        bt $(INTEL_PSE), %edx
     113        jnc pse_unsupported
     114               
     115                /* Map kernel and turn paging on */
     116                pm_status $status_pse
     117                call map_kernel_pse
     118                jmp stack_init
     119       
     120#endif /* PROCESSOR_i486 */
     121       
     122        pse_unsupported:
     123               
     124                /* Map kernel and turn paging on */
     125                pm_status $status_non_pse
     126                call map_kernel
     127       
     128        stack_init:
    103129       
    104130        /* Create the first stack frame */
     
    106132        movl %esp, %ebp
    107133       
    108         pm2_status $status_prot2
     134        pm2_status $status_prot3
    109135       
    110136        /* Call arch_pre_main(grub_eax, grub_ebx) */
     
    124150                jmp hlt0
    125151
    126 /** Calculate unmapped address of the end of the kernel. */
    127 calc_end_of_kernel:
    128         movl $hardcoded_load_address, %edi
    129         andl $0x7fffffff, %edi
    130         movl (%edi), %esi
    131         andl $0x7fffffff, %esi
    132        
    133         movl $hardcoded_ktext_size, %edi
    134         andl $0x7fffffff, %edi
    135         addl (%edi), %esi
    136         andl $0x7fffffff, %esi
    137        
    138         movl $hardcoded_kdata_size, %edi
    139         andl $0x7fffffff, %edi
    140         addl (%edi), %esi
    141         andl $0x7fffffff, %esi
    142         movl %esi, end_of_kernel
     152/** Setup mapping for the kernel (PSE variant)
     153 *
     154 * Setup mapping for both the unmapped and mapped sections
     155 * of the kernel. For simplicity, we map the entire 4G space.
     156 *
     157 */
     158.global map_kernel_pse
     159map_kernel_pse:
     160        /* Paging features */
     161        movl %cr4, %ecx
     162        orl $(1 << 4), %ecx      /* PSE on */
     163        andl $(~(1 << 5)), %ecx  /* PAE off */
     164        movl %ecx, %cr4
     165       
     166        movl $(page_directory + 0), %esi
     167        movl $(page_directory + 2048), %edi
     168        xorl %ecx, %ecx
     169        xorl %ebx, %ebx
     170       
     171        floop_pse:
     172                movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
     173                orl %ebx, %eax
     174                /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
     175                movl %eax, (%esi, %ecx, 4)
     176                /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
     177                movl %eax, (%edi, %ecx, 4)
     178                addl $(4 * 1024 * 1024), %ebx
     179               
     180                incl %ecx
     181                cmpl $512, %ecx
     182                jl floop_pse
     183       
     184        movl %esi, %cr3
     185       
     186        movl %cr0, %ebx
     187        orl $(1 << 31), %ebx  /* paging on */
     188        movl %ebx, %cr0
    143189        ret
    144190
    145 /** Find free 2M (+4k for alignment) region where to store page tables */
    146 find_mem_for_pt:
    147         /* Check if multiboot info is present */
    148         cmpl $0x2BADB002, grub_eax
    149         je check_multiboot_map
    150         ret
    151 check_multiboot_map:
    152         /* Copy address of the multiboot info to ebx */
    153         movl grub_ebx, %ebx
    154         /* Check if memory map flag is present */
    155         movl (%ebx), %edx
    156         andl $(1 << 6), %edx
    157         jnz use_multiboot_map
    158         ret
    159 use_multiboot_map:
    160         /* Copy address of the memory map to edx */
    161         movl 48(%ebx), %edx
    162         movl %edx, %ecx
    163         addl 44(%ebx), %ecx
    164         /* Find a free region at least 2M in size */
    165         check_memmap_loop:
    166                 /* Is this a free region? */
    167                 cmp $1, 20(%edx)
    168                 jnz next_region
    169                 /* Check size */
    170                 cmp $0, 16(%edx)
    171                 jnz next_region
    172                 cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
    173                 jbe next_region
    174                 cmp $0, 8(%edx)
    175                 jz found_region
    176         next_region:
    177                 cmp %ecx, %edx
    178                 jbe next_region_do
    179                 ret
    180         next_region_do:
    181                 addl (%edx), %edx
    182                 addl $4, %edx
    183                 jmp check_memmap_loop
    184         found_region:
    185                 /* Use end of the found region */
    186                 mov 4(%edx), %ecx
    187                 add 12(%edx), %ecx
    188                 sub $(2 * 1024 * 1024), %ecx
    189                 mov %ecx, free_area
    190         ret
    191                
    192 
    193 /** Setup mapping for the kernel.
     191/** Setup mapping for the kernel (non-PSE variant).
    194192 *
    195193 * Setup mapping for both the unmapped and mapped sections
     
    204202        movl %ecx, %cr4
    205203       
    206         call calc_end_of_kernel
     204        call calc_kernel_end
    207205        call find_mem_for_pt
    208         mov end_of_kernel, %esi
     206       
     207        mov kernel_end, %esi
    209208        mov free_area, %ecx
     209       
    210210        cmpl %esi, %ecx
    211         jbe use_end_of_kernel
    212         mov %ecx, %esi
    213         /* Align address down to 4k */
    214         andl $(~4095), %esi
    215 use_end_of_kernel:
    216        
    217         /* Align address to 4k */
    218         addl $4095, %esi
    219         andl $(~4095), %esi
    220        
    221         /* Allocate space for page tables*/     
    222         movl %esi, pt_loc
    223         movl $ballocs, %edi
     211        jbe use_kernel_end
     212               
     213                mov %ecx, %esi
     214               
     215                /* Align address down to 4k */
     216                andl $(~4095), %esi
     217               
     218        use_kernel_end:
     219               
     220                /* Align address to 4k */
     221                addl $4095, %esi
     222                andl $(~4095), %esi
     223               
     224                /* Allocate space for page tables */
     225                movl %esi, pt_loc
     226                movl $ballocs, %edi
     227                andl $0x7fffffff, %edi
     228               
     229                movl %esi, (%edi)
     230                addl $4, %edi
     231                movl $(2 * 1024 * 1024), (%edi)
     232               
     233                /* Fill page tables */
     234                xorl %ecx, %ecx
     235                xorl %ebx, %ebx
     236               
     237                floop_pt:
     238                        movl $((1 << 1) | (1 << 0)), %eax
     239                        orl %ebx, %eax
     240                        movl %eax, (%esi, %ecx, 4)
     241                        addl $(4 * 1024), %ebx
     242                       
     243                        incl %ecx
     244                        cmpl $(512 * 1024), %ecx
     245                       
     246                        jl floop_pt
     247               
     248                /* Fill page directory */
     249                movl $(page_directory + 0), %esi
     250                movl $(page_directory + 2048), %edi
     251                xorl %ecx, %ecx
     252                movl pt_loc, %ebx
     253               
     254                floop:
     255                        movl $((1 << 1) | (1 << 0)), %eax
     256                        orl %ebx, %eax
     257                       
     258                        /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
     259                        movl %eax, (%esi, %ecx, 4)
     260                       
     261                        /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
     262                        movl %eax, (%edi, %ecx, 4)
     263                        addl $(4 * 1024), %ebx
     264                       
     265                        incl %ecx
     266                        cmpl $512, %ecx
     267                       
     268                        jl floop
     269               
     270                movl %esi, %cr3
     271               
     272                movl %cr0, %ebx
     273                orl $(1 << 31), %ebx  /* paging on */
     274                movl %ebx, %cr0
     275               
     276                ret
     277
     278/** Calculate unmapped address of the end of the kernel. */
     279calc_kernel_end:
     280        movl $hardcoded_load_address, %edi
    224281        andl $0x7fffffff, %edi
    225         movl %esi, (%edi)
    226         addl $4, %edi
    227         movl $(2*1024*1024), (%edi)
    228        
    229         /* Fill page tables */
    230         xorl %ecx, %ecx
    231         xorl %ebx, %ebx
    232        
    233         floop_pt:
    234                 movl $((1 << 1) | (1 << 0)), %eax
    235                 orl %ebx, %eax
    236                 movl %eax, (%esi, %ecx, 4)
    237                 addl $(4 * 1024), %ebx
    238                
    239                 incl %ecx
    240                 cmpl $(512 * 1024), %ecx
    241                 jl floop_pt
    242        
    243         /* Fill page directory */
    244         movl $(page_directory + 0), %esi
    245         movl $(page_directory + 2048), %edi
    246         xorl %ecx, %ecx
    247         movl pt_loc, %ebx
    248        
    249         floop:
    250                 movl $((1 << 1) | (1 << 0)), %eax
    251                 orl %ebx, %eax
    252                 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
    253                 movl %eax, (%esi, %ecx, 4)
    254                 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
    255                 movl %eax, (%edi, %ecx, 4)
    256                 addl $(4 * 1024), %ebx
    257                
    258                 incl %ecx
    259                 cmpl $512, %ecx
    260                 jl floop
    261        
    262         movl %esi, %cr3
    263        
    264         movl %cr0, %ebx
    265         orl $(1 << 31), %ebx  /* paging on */
    266         movl %ebx, %cr0
     282        movl (%edi), %esi
     283        andl $0x7fffffff, %esi
     284       
     285        movl $hardcoded_ktext_size, %edi
     286        andl $0x7fffffff, %edi
     287        addl (%edi), %esi
     288        andl $0x7fffffff, %esi
     289       
     290        movl $hardcoded_kdata_size, %edi
     291        andl $0x7fffffff, %edi
     292        addl (%edi), %esi
     293        andl $0x7fffffff, %esi
     294        movl %esi, kernel_end
     295       
    267296        ret
     297
     298/** Find free 2M (+4k for alignment) region where to store page tables */
     299find_mem_for_pt:
     300        /* Check if multiboot info is present */
     301        cmpl $MULTIBOOT_LOADER_MAGIC, grub_eax
     302        je check_multiboot_map
     303               
     304                ret
     305       
     306        check_multiboot_map:
     307               
     308                /* Copy address of the multiboot info to ebx */
     309                movl grub_ebx, %ebx
     310               
     311                /* Check if memory map flag is present */
     312                movl (%ebx), %edx
     313                andl $(1 << 6), %edx
     314                jnz use_multiboot_map
     315                       
     316                        ret
     317               
     318        use_multiboot_map:
     319               
     320                /* Copy address of the memory map to edx */
     321                movl 48(%ebx), %edx
     322                movl %edx, %ecx
     323               
     324                addl 44(%ebx), %ecx
     325               
     326                /* Find a free region at least 2M in size */
     327                check_memmap_loop:
     328                       
     329                        /* Is this a free region? */
     330                        cmp $1, 20(%edx)
     331                        jnz next_region
     332                       
     333                        /* Check size */
     334                        cmp $0, 16(%edx)
     335                        jnz next_region
     336                       
     337                        cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
     338                        jbe next_region
     339                       
     340                        cmp $0, 8(%edx)
     341                        jz found_region
     342               
     343                next_region:
     344                       
     345                        cmp %ecx, %edx
     346                        jbe next_region_do
     347                       
     348                                ret
     349               
     350                next_region_do:
     351                       
     352                        addl (%edx), %edx
     353                        addl $4, %edx
     354                        jmp check_memmap_loop
     355                       
     356                found_region:
     357                       
     358                        /* Use end of the found region */
     359                        mov 4(%edx), %ecx
     360                        add 12(%edx), %ecx
     361                        sub $(2 * 1024 * 1024), %ecx
     362                        mov %ecx, free_area
     363                       
     364                        ret
    268365
    269366/** Print string to EGA display (in light red) and halt.
     
    610707grub_eax:
    611708        .long 0
    612 
    613709grub_ebx:
    614710        .long 0
     
    616712pt_loc:
    617713        .long 0
    618 end_of_kernel:
     714kernel_end:
    619715        .long 0
    620716free_area:
    621717        .long 0
    622718
    623 err_pse:
    624         .asciz "Page Size Extension not supported. System halted."
    625 
    626719status_prot:
    627720        .asciz "[prot] "
     721status_pse:
     722        .asciz "[pse] "
     723status_non_pse:
     724        .asciz "[non_pse] "
    628725status_vesa_copy:
    629726        .asciz "[vesa_copy] "
     
    634731status_prot2:
    635732        .asciz "[prot2] "
     733status_prot3:
     734        .asciz "[prot3] "
    636735status_main:
    637736        .asciz "[main] "
  • kernel/arch/ia32/src/syscall.c

    r921b84f r5fb32c5  
    4040
    4141#ifndef PROCESSOR_i486
     42
    4243/** Enable & setup support for SYSENTER/SYSEXIT */
    4344void syscall_setup_cpu(void)
     
    5051        write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
    5152}
    52 #endif
     53
     54#endif /* PROCESSOR_i486 */
    5355
    5456/** @}
  • kernel/generic/include/ipc/ipc.h

    r921b84f r5fb32c5  
    9898typedef struct {
    9999        sysarg_t args[IPC_CALL_LEN];
    100         /** Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME. */
     100        /**
     101         * Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME,
     102         * or the task which answered the call.
     103         */
    101104        task_id_t task_id;
    102105        /** Phone which made or last masqueraded this call. */
  • kernel/generic/src/ipc/ipc.c

    r921b84f r5fb32c5  
    230230                }
    231231        }
     232
     233        call->data.task_id = TASK->taskid;
    232234       
    233235        if (do_lock)
  • kernel/generic/src/ipc/sysipc.c

    r921b84f r5fb32c5  
    253253                        /* The connection was accepted */
    254254                        phone_connect(phoneid, &answer->sender->answerbox);
    255                         /* Set 'task ID' as arg3 and arg4 of response */
    256                         IPC_SET_ARG3(answer->data, LOWER32(TASK->taskid));
    257                         IPC_SET_ARG4(answer->data, UPPER32(TASK->taskid));
    258255                        /* Set 'phone hash' as arg5 of response */
    259256                        IPC_SET_ARG5(answer->data,
  • uspace/app/bdsh/compl.c

    r921b84f r5fb32c5  
    11/*
    22 * Copyright (c) 2011 Jiri Svoboda
     3 * Copyright (c) 2011 Martin Sucha
    34 * All rights reserved.
    45 *
     
    3738#include "compl.h"
    3839#include "exec.h"
     40#include "tok.h"
    3941
    4042static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state);
     
    8890{
    8991        compl_t *cs = NULL;
    90         size_t p;
    9192        size_t pref_size;
    9293        char *stext = NULL;
     
    9697        static const char *dirlist_arg[] = { ".", NULL };
    9798        int retval;
     99        tokenizer_t tok;
     100        token_t tokens[WORD_MAX];
     101        unsigned int current_token;
     102        size_t tokens_length;
    98103
    99104        cs = calloc(1, sizeof(compl_t));
     
    103108        }
    104109
    105         /*
    106          * Copy token pointed to by caret from start up to the caret.
    107          * XXX Ideally we would use the standard tokenizer.
    108          */
    109         p = pos;
    110         while (p > 0 && text[p - 1] != (wchar_t) ' ')
    111                 --p;
    112         *cstart = p;
    113 
    114110        /* Convert text buffer to string */
    115         stext = wstr_to_astr(text + *cstart);
     111        stext = wstr_to_astr(text);
    116112        if (stext == NULL) {
    117113                retval = ENOMEM;
    118114                goto error;
    119115        }
    120 
    121         /* Extract the prefix being completed */
     116       
     117        /* Tokenize the input string */
     118        retval = tok_init(&tok, stext, tokens, WORD_MAX);
     119        if (retval != EOK) {
     120                goto error;
     121        }
     122       
     123        retval = tok_tokenize(&tok, &tokens_length);
     124        if (retval != EOK) {
     125                goto error;
     126        }
     127       
     128        /* Find the current token */
     129        for (current_token = 0; current_token < tokens_length; current_token++) {
     130                token_t *t = &tokens[current_token];
     131                size_t end = t->char_start + t->char_length;
     132                /* Check if the caret lies inside the token or immediately
     133                 * after it
     134                 */
     135                if (t->char_start <= pos && pos <= end) {
     136                        break;
     137                }
     138        }
     139       
     140        if (tokens[current_token].type != TOKTYPE_SPACE) {
     141                *cstart = tokens[current_token].char_start;
     142        }
     143        else {
     144                *cstart = pos;
     145        }
     146       
     147        /* Extract the prefix being completed
     148         * XXX: handle strings, etc.
     149         */
    122150        pref_size = str_lsize(stext, pos - *cstart);
    123151        prefix = malloc(pref_size + 1);
     
    127155        }
    128156
    129         str_ncpy(prefix, pref_size + 1, stext, pref_size);
     157        str_ncpy(prefix, pref_size + 1, stext +
     158            tokens[current_token].byte_start, pref_size);
    130159
    131160        /*
     
    133162         * We look at the previous token. If there is none or it is a pipe
    134163         * ('|'), it is a command, otherwise it is an argument.
    135          * XXX Again we should use the standard tokenizer/parser.
    136164         */
    137165
    138166        /* Skip any whitespace before current token */
    139         while (p > 0 && text[p - 1] == (wchar_t) ' ')
    140                 --p;
     167        int prev_token = current_token - 1;
     168        if (prev_token != -1 && tokens[prev_token].type == TOKTYPE_SPACE) {
     169                prev_token--;
     170        }
    141171
    142172        /*
     
    144174         * follows a pipe token.
    145175         */
    146         if (p == 0 || text[p - 1] == '|')
     176        if (prev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE)
    147177                cs->is_command = true;
    148178        else
     
    189219
    190220        cs->prefix_len = str_length(cs->prefix);
     221       
     222        tok_fini(&tok);
    191223
    192224        *state = cs;
     
    195227error:
    196228        /* Error cleanup */
     229       
     230        tok_fini(&tok);
    197231
    198232        if (cs != NULL && cs->path_list != NULL) {
  • uspace/app/bdsh/input.c

    r921b84f r5fb32c5  
    22 * Copyright (c) 2008 Tim Post
    33 * Copyright (c) 2011 Jiri Svoboda
     4 * Copyright (c) 2011 Martin Sucha
    45 * All rights reserved.
    56 *
     
    6768{
    6869        char *cmd[WORD_MAX];
     70        token_t tokens_space[WORD_MAX];
     71        token_t *tokens = tokens_space;
    6972        int rc = 0;
    7073        tokenizer_t tok;
    71         int i, pipe_count, processed_pipes;
    72         int pipe_pos[2];
    73         char **actual_cmd;
     74        unsigned int i, pipe_count, processed_pipes;
     75        unsigned int pipe_pos[2];
    7476        char *redir_from = NULL;
    7577        char *redir_to = NULL;
     
    7880                return CL_EFAIL;
    7981
    80         rc = tok_init(&tok, usr->line, cmd, WORD_MAX);
     82        rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
    8183        if (rc != EOK) {
    8284                goto finit;
    8385        }
    8486       
    85         rc = tok_tokenize(&tok);
     87        size_t tokens_length;
     88        rc = tok_tokenize(&tok, &tokens_length);
    8689        if (rc != EOK) {
    8790                goto finit;
     91        }
     92       
     93        if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
     94                tokens++;
     95                tokens_length--;
     96        }
     97       
     98        if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {
     99                tokens_length--;
    88100        }
    89101       
     
    93105         * First find the pipes and check that there are no more
    94106         */
    95         int cmd_length = 0;
    96         for (i = 0, pipe_count = 0; cmd[i] != NULL; i++, cmd_length++) {
    97                 if (cmd[i][0] == '|') {
     107        for (i = 0, pipe_count = 0; i < tokens_length; i++) {
     108                if (tokens[i].type == TOKTYPE_PIPE) {
    98109                        if (pipe_count >= 2) {
    99110                                print_pipe_usage();
     
    106117        }
    107118       
    108         actual_cmd = cmd;
     119        unsigned int cmd_token_start = 0;
     120        unsigned int cmd_token_end = tokens_length;
     121       
    109122        processed_pipes = 0;
    110123       
    111124        /* Check if the first part (from <file> |) is present */
    112         if (pipe_count > 0 && pipe_pos[0] == 2 && str_cmp(cmd[0], "from") == 0) {
     125        if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
    113126                /* Ignore the first three tokens (from, file, pipe) and set from */
    114                 redir_from = cmd[1];
    115                 actual_cmd = cmd + 3;
     127                redir_from = tokens[2].text;
     128                cmd_token_start = pipe_pos[0]+1;
    116129                processed_pipes++;
    117130        }
     
    119132        /* Check if the second part (| to <file>) is present */
    120133        if ((pipe_count - processed_pipes) > 0 &&
    121             pipe_pos[processed_pipes] == cmd_length - 3 &&
    122             str_cmp(cmd[cmd_length-2], "to") == 0) {
     134            (pipe_pos[processed_pipes] == tokens_length - 4 ||
     135            (pipe_pos[processed_pipes] == tokens_length - 5 &&
     136            tokens[tokens_length-4].type == TOKTYPE_SPACE )) &&
     137            str_cmp(tokens[tokens_length-3].text, "to") == 0) {
    123138                /* Ignore the last three tokens (pipe, to, file) and set to */
    124                 redir_to = cmd[cmd_length-1];
    125                 cmd[cmd_length-3] = NULL;
    126                 cmd_length -= 3;
     139                redir_to = tokens[tokens_length-1].text;
     140                cmd_token_end = pipe_pos[processed_pipes];
    127141                processed_pipes++;
    128142        }
     
    134148        }
    135149       
    136         if (actual_cmd[0] == NULL) {
     150        /* Convert tokens of the command to string array */
     151        unsigned int cmd_pos = 0;
     152        for (i = cmd_token_start; i < cmd_token_end; i++) {
     153                if (tokens[i].type != TOKTYPE_SPACE) {
     154                        cmd[cmd_pos++] = tokens[i].text;
     155                }
     156        }
     157        cmd[cmd_pos++] = NULL;
     158       
     159        if (cmd[0] == NULL) {
    137160                print_pipe_usage();
    138161                rc = ENOTSUP;
     
    170193        }
    171194
    172         if (str_cmp(actual_cmd[0], "batch") == 0 && actual_cmd[1] != NULL) {
    173                 FILE *batch = fopen(actual_cmd[1], "r");
     195        if (str_cmp(cmd[0], "batch") == 0 && cmd[1] != NULL) {
     196                FILE *batch = fopen(cmd[1], "r");
    174197                if (batch == NULL) {
    175                         printf("Cannot open file %s\n", actual_cmd[1]);
     198                        printf("Cannot open file %s\n", cmd[1]);
    176199                        rc = errno;
    177200                } else {
     
    211234                }
    212235        } else {
    213                 rc = run_command(actual_cmd, usr, &new_iostate);
    214         }       
     236                rc = run_command(cmd, usr, &new_iostate);
     237        }
    215238       
    216239finit_with_files:
  • uspace/app/bdsh/tok.c

    r921b84f r5fb32c5  
    4242static bool tok_pending_chars(tokenizer_t *);
    4343static int tok_finish_string(tokenizer_t *);
     44static void tok_start_token(tokenizer_t *, token_type_t);
    4445
    4546/** Initialize the token parser
     
    5051 * @param max_tokens number of elements of the out_tokens array
    5152 */
    52 int tok_init(tokenizer_t *tok, char *input, char **out_tokens,
     53int tok_init(tokenizer_t *tok, char *input, token_t *out_tokens,
    5354    size_t max_tokens)
    5455{       
    5556        tok->in = input;
    5657        tok->in_offset = 0;
     58        tok->last_in_offset = 0;
     59        tok->in_char_offset = 0;
     60        tok->last_in_char_offset = 0;
    5761       
    5862        tok->outtok = out_tokens;
    5963        tok->outtok_offset = 0;
    60         /* Leave one slot for a null terminator */
    61         assert(max_tokens > 0);
    62         tok->outtok_size = max_tokens - 1;
     64        tok->outtok_size = max_tokens;
    6365       
    6466        /* Prepare a buffer where all the token strings will be stored */
     
    8789
    8890/** Tokenize the input string into the tokens */
    89 int tok_tokenize(tokenizer_t *tok)
     91int tok_tokenize(tokenizer_t *tok, size_t *tokens_length)
    9092{
    9193        int rc;
    92         wchar_t cur_char;
     94        wchar_t next_char;
    9395       
    9496        /* Read the input line char by char and append tokens */
    95         while ((cur_char = tok_get_char(tok)) != 0) {
    96                 if (cur_char == ' ') {
    97                         /* Spaces delimit tokens, but are not processed in any way
    98                          * Push the token if there is any.
     97        while ((next_char = tok_look_char(tok)) != 0) {
     98                if (next_char == ' ') {
     99                        /* Push the token if there is any.
    99100                         * There may not be any pending char for a token in case
    100101                         * there are several spaces in the input.
     
    106107                                }
    107108                        }
    108                 }
    109                 else if (cur_char == '|') {
    110                         /* Pipes are tokens that are delimiters and should be output
    111                          * as a separate token
     109                        tok_start_token(tok, TOKTYPE_SPACE);
     110                        /* Eat all the spaces */
     111                        while (tok_look_char(tok) == ' ') {
     112                                tok_push_char(tok, tok_get_char(tok));
     113                        }
     114                        tok_push_token(tok);
     115                       
     116                }
     117                else if (next_char == '|') {
     118                        /* Pipes are tokens that are delimiters and should be
     119                         * output as a separate token
    112120                         */
    113121                        if (tok_pending_chars(tok)) {
     
    118126                        }
    119127                       
    120                         rc = tok_push_char(tok, '|');
     128                        tok_start_token(tok, TOKTYPE_PIPE);
     129                       
     130                        rc = tok_push_char(tok, tok_get_char(tok));
    121131                        if (rc != EOK) {
    122132                                return rc;
     
    128138                        }
    129139                }
    130                 else if (cur_char == '\'') {
     140                else if (next_char == '\'') {
    131141                        /* A string starts with a quote (') and ends again with a quote.
    132142                         * A literal quote is written as ''
    133143                         */
     144                        tok_start_token(tok, TOKTYPE_TEXT);
     145                        /* Eat the quote */
     146                        tok_get_char(tok);
    134147                        rc = tok_finish_string(tok);
    135148                        if (rc != EOK) {
     
    138151                }
    139152                else {
     153                        if (!tok_pending_chars(tok)) {
     154                                tok_start_token(tok, TOKTYPE_TEXT);
     155                        }
    140156                        /* If we are handling any other character, just append it to
    141157                         * the current token.
    142158                         */
    143                         rc = tok_push_char(tok, cur_char);
     159                        rc = tok_push_char(tok, tok_get_char(tok));
    144160                        if (rc != EOK) {
    145161                                return rc;
     
    156172        }
    157173       
    158         /* We always have a space for the terminator, as we
    159          * reserved it in tok_init */
    160         tok->outtok[tok->outtok_offset] = 0;
     174        *tokens_length = tok->outtok_offset;
    161175       
    162176        return EOK;
     
    167181{
    168182        int rc;
    169         wchar_t cur_char;
    170        
    171         while ((cur_char = tok_get_char(tok)) != 0) {
    172                 if (cur_char == '\'') {
     183        wchar_t next_char;
     184       
     185        while ((next_char = tok_look_char(tok)) != 0) {
     186                if (next_char == '\'') {
     187                        /* Eat the quote */
     188                        tok_get_char(tok);
    173189                        if (tok_look_char(tok) == '\'') {
    174190                                /* Encode a single literal quote */
     
    187203                }
    188204                else {
    189                         rc = tok_push_char(tok, cur_char);
     205                        rc = tok_push_char(tok, tok_get_char(tok));
    190206                        if (rc != EOK) {
    191207                                return rc;
     
    201217wchar_t tok_get_char(tokenizer_t *tok)
    202218{
     219        tok->in_char_offset++;
    203220        return str_decode(tok->in, &tok->in_offset, STR_NO_LIMIT);
    204221}
     
    207224wchar_t tok_look_char(tokenizer_t *tok)
    208225{
    209         size_t old_offset = tok->in_offset;
     226        unsigned int old_offset = tok->in_offset;
     227        unsigned int old_char_offset = tok->in_char_offset;
    210228        wchar_t ret = tok_get_char(tok);
    211229        tok->in_offset = old_offset;
     230        tok->in_char_offset = old_char_offset;
    212231        return ret;
    213232}
     
    219238}
    220239
     240void tok_start_token(tokenizer_t *tok, token_type_t type)
     241{
     242        tok->current_type = type;
     243}
     244
    221245/** Push the current token to the output array */
    222246int tok_push_token(tokenizer_t *tok)
     
    231255       
    232256        tok->outbuf[tok->outbuf_offset++] = 0;
    233         tok->outtok[tok->outtok_offset++] = tok->outbuf + tok->outbuf_last_start;
     257        token_t *tokinfo = &tok->outtok[tok->outtok_offset++];
     258        tokinfo->type = tok->current_type;
     259        tokinfo->text = tok->outbuf + tok->outbuf_last_start;
     260        tokinfo->byte_start = tok->last_in_offset;
     261        tokinfo->byte_length = tok->in_offset - tok->last_in_offset;
     262        tokinfo->char_start = tok->last_in_char_offset;
     263        tokinfo->char_length = tok->in_char_offset - tok->last_in_char_offset;
    234264        tok->outbuf_last_start = tok->outbuf_offset;
     265       
     266        /* We have consumed the first char of the next token already */
     267        tok->last_in_offset = tok->in_offset;
     268        tok->last_in_char_offset = tok->in_char_offset;
    235269       
    236270        return EOK;
  • uspace/app/bdsh/tok.h

    r921b84f r5fb32c5  
    3030#define TOK_H
    3131
     32typedef enum {
     33        TOKTYPE_TEXT,
     34        TOKTYPE_PIPE,
     35        TOKTYPE_SPACE
     36} token_type_t;
     37
     38typedef struct {
     39        char *text;
     40        unsigned int byte_start;
     41        unsigned int char_start;
     42        size_t byte_length;
     43        size_t char_length;
     44        token_type_t type;
     45} token_t;
     46
    3247typedef struct {
    3348        char *in;
    34         size_t in_offset;
     49        unsigned int in_offset;
     50        unsigned int last_in_offset;
     51        unsigned int in_char_offset;
     52        unsigned int last_in_char_offset;
    3553       
    3654        char *outbuf;
     
    3957        size_t outbuf_last_start;
    4058       
    41         char **outtok;
     59        token_t *outtok;
     60        token_type_t current_type;
    4261        size_t outtok_offset;
    4362        size_t outtok_size;
    4463} tokenizer_t;
    4564
    46 extern int tok_init(tokenizer_t *, char *, char **, size_t);
     65extern int tok_init(tokenizer_t *, char *, token_t *, size_t);
    4766extern void tok_fini(tokenizer_t *);
    48 extern int tok_tokenize(tokenizer_t *);
     67extern int tok_tokenize(tokenizer_t *, size_t *);
    4968
    5069#endif
  • uspace/lib/c/arch/ia32/Makefile.common

    r921b84f r5fb32c5  
    2828
    2929CLANG_ARCH = i386
     30
    3031ifeq ($(PROCESSOR),i486)
    31 GCC_CFLAGS += -march=i486 -fno-omit-frame-pointer
     32        GCC_CFLAGS += -march=i486 -fno-omit-frame-pointer
    3233else
    33 GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
     34        GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
    3435endif
    3536
  • uspace/lib/c/arch/ia32/src/entry.S

    r921b84f r5fb32c5  
    4646        mov %ax, %fs
    4747        # Do not set %gs, it contains descriptor that can see TLS
    48 
     48       
    4949#ifndef PROCESSOR_i486 
    5050        # Detect the mechanism used for making syscalls
     
    5353        bt $(INTEL_SEP), %edx
    5454        jnc 0f
    55         leal __syscall_fast_func, %eax
    56         movl $__syscall_fast, (%eax)
    57 0:
     55                leal __syscall_fast_func, %eax
     56                movl $__syscall_fast, (%eax)
     57        0:
    5858#endif
     59       
    5960        #
    6061        # Create the first stack frame.
  • uspace/lib/c/generic/async.c

    r921b84f r5fb32c5  
    9898#include <ipc/ipc.h>
    9999#include <async.h>
     100#include "private/async.h"
    100101#undef LIBC_ASYNC_C_
    101102
     
    113114#include <stdlib.h>
    114115#include <macros.h>
    115 #include "private/async.h"
    116116
    117117#define CLIENT_HASH_TABLE_BUCKETS  32
     
    996996        session_ns->arg3 = 0;
    997997       
     998        fibril_mutex_initialize(&session_ns->remote_state_mtx);
     999        session_ns->remote_state_data = NULL;
     1000       
    9981001        list_initialize(&session_ns->exch_list);
    9991002        fibril_mutex_initialize(&session_ns->mutex);
     
    14721475                return ENOENT;
    14731476       
    1474         task_id_t task_id;
    1475         sysarg_t task_id_lo;
    1476         sysarg_t task_id_hi;
    14771477        sysarg_t phone_hash;
    1478         int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    1479             NULL, NULL, &task_id_lo, &task_id_hi, &phone_hash);
     1478        sysarg_t rc;
     1479
     1480        aid_t req;
     1481        ipc_call_t answer;
     1482        req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     1483            &answer);
     1484        async_wait_for(req, &rc);
    14801485        if (rc != EOK)
    1481                 return rc;
    1482 
    1483         task_id = (task_id_t) MERGE_LOUP32(task_id_lo, task_id_hi);
    1484        
     1486                return (int) rc;
     1487
     1488        phone_hash = IPC_GET_ARG5(answer);
     1489
    14851490        if (client_receiver != NULL)
    1486                 async_new_connection(task_id, phone_hash, 0, NULL,
     1491                async_new_connection(answer.in_task_id, phone_hash, 0, NULL,
    14871492                    client_receiver, carg);
    14881493       
     
    15591564        sess->arg3 = 0;
    15601565       
     1566        fibril_mutex_initialize(&sess->remote_state_mtx);
     1567        sess->remote_state_data = NULL;
     1568       
    15611569        list_initialize(&sess->exch_list);
    15621570        fibril_mutex_initialize(&sess->mutex);
     
    16401648        sess->arg3 = arg3;
    16411649       
     1650        fibril_mutex_initialize(&sess->remote_state_mtx);
     1651        sess->remote_state_data = NULL;
     1652       
    16421653        list_initialize(&sess->exch_list);
    16431654        fibril_mutex_initialize(&sess->mutex);
     
    16901701        sess->arg3 = arg3;
    16911702       
     1703        fibril_mutex_initialize(&sess->remote_state_mtx);
     1704        sess->remote_state_data = NULL;
     1705       
    16921706        list_initialize(&sess->exch_list);
    16931707        fibril_mutex_initialize(&sess->mutex);
     
    17201734        sess->arg2 = 0;
    17211735        sess->arg3 = 0;
     1736       
     1737        fibril_mutex_initialize(&sess->remote_state_mtx);
     1738        sess->remote_state_data = NULL;
    17221739       
    17231740        list_initialize(&sess->exch_list);
     
    23842401        sess->arg3 = 0;
    23852402       
     2403        fibril_mutex_initialize(&sess->remote_state_mtx);
     2404        sess->remote_state_data = NULL;
     2405       
    23862406        list_initialize(&sess->exch_list);
    23872407        fibril_mutex_initialize(&sess->mutex);
     
    24302450        sess->arg3 = 0;
    24312451       
     2452        fibril_mutex_initialize(&sess->remote_state_mtx);
     2453        sess->remote_state_data = NULL;
     2454       
    24322455        list_initialize(&sess->exch_list);
    24332456        fibril_mutex_initialize(&sess->mutex);
     
    24712494        sess->arg2 = 0;
    24722495        sess->arg3 = 0;
     2496       
     2497        fibril_mutex_initialize(&sess->remote_state_mtx);
     2498        sess->remote_state_data = NULL;
    24732499       
    24742500        list_initialize(&sess->exch_list);
     
    25122538}
    25132539
     2540/** Lock and get session remote state
     2541 *
     2542 * Lock and get the local replica of the remote state
     2543 * in stateful sessions. The call should be paired
     2544 * with async_remote_state_release*().
     2545 *
     2546 * @param[in] sess Stateful session.
     2547 *
     2548 * @return Local replica of the remote state.
     2549 *
     2550 */
     2551void *async_remote_state_acquire(async_sess_t *sess)
     2552{
     2553        fibril_mutex_lock(&sess->remote_state_mtx);
     2554        return sess->remote_state_data;
     2555}
     2556
     2557/** Update the session remote state
     2558 *
     2559 * Update the local replica of the remote state
     2560 * in stateful sessions. The remote state must
     2561 * be already locked.
     2562 *
     2563 * @param[in] sess  Stateful session.
     2564 * @param[in] state New local replica of the remote state.
     2565 *
     2566 */
     2567void async_remote_state_update(async_sess_t *sess, void *state)
     2568{
     2569        assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
     2570        sess->remote_state_data = state;
     2571}
     2572
     2573/** Release the session remote state
     2574 *
     2575 * Unlock the local replica of the remote state
     2576 * in stateful sessions.
     2577 *
     2578 * @param[in] sess Stateful session.
     2579 *
     2580 */
     2581void async_remote_state_release(async_sess_t *sess)
     2582{
     2583        assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
     2584       
     2585        fibril_mutex_unlock(&sess->remote_state_mtx);
     2586}
     2587
     2588/** Release the session remote state and end an exchange
     2589 *
     2590 * Unlock the local replica of the remote state
     2591 * in stateful sessions. This is convenience function
     2592 * which gets the session pointer from the exchange
     2593 * and also ends the exchange.
     2594 *
     2595 * @param[in] exch Stateful session's exchange.
     2596 *
     2597 */
     2598void async_remote_state_release_exchange(async_exch_t *exch)
     2599{
     2600        if (exch == NULL)
     2601                return;
     2602       
     2603        async_sess_t *sess = exch->sess;
     2604        assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
     2605       
     2606        async_exchange_end(exch);
     2607        fibril_mutex_unlock(&sess->remote_state_mtx);
     2608}
     2609
    25142610/** @}
    25152611 */
  • uspace/lib/c/generic/async_obsolete.c

    r921b84f r5fb32c5  
    3838#include <async.h>
    3939#include <async_obsolete.h>
     40#include "private/async.h"
    4041#undef LIBC_ASYNC_C_
    4142#undef LIBC_ASYNC_OBSOLETE_C_
     
    4445#include <malloc.h>
    4546#include <errno.h>
    46 #include "private/async.h"
    4747
    4848/** Send message and return id of the sent message.
  • uspace/lib/c/generic/ipc.c

    r921b84f r5fb32c5  
    4747#include <futex.h>
    4848#include <fibril.h>
     49#include <macros.h>
    4950
    5051/**
     
    611612/** Request callback connection.
    612613 *
    613  * The @a taskhash and @a phonehash identifiers returned
     614 * The @a task_id and @a phonehash identifiers returned
    614615 * by the kernel can be used for connection tracking.
    615616 *
     
    618619 * @param arg2      User defined argument.
    619620 * @param arg3      User defined argument.
    620  * @param taskhash  Opaque identifier of the client task.
     621 * @param task_id   Identifier of the client task.
    621622 * @param phonehash Opaque identifier of the phone that will
    622623 *                  be used for incoming calls.
     
    626627 */
    627628int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    628     sysarg_t *taskhash, sysarg_t *phonehash)
    629 {
    630         return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2,
    631             arg3, NULL, NULL, NULL, taskhash, phonehash);
     629    task_id_t *task_id, sysarg_t *phonehash)
     630{
     631        ipc_call_t data;
     632        int rc = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid,
     633            IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, (sysarg_t) &data);
     634        if (rc == EOK) {
     635                *task_id = data.in_task_id;
     636                *phonehash = IPC_GET_ARG5(data);
     637        }       
     638        return rc;
    632639}
    633640
  • uspace/lib/c/generic/private/async.h

    r921b84f r5fb32c5  
    3636#define LIBC_PRIVATE_ASYNC_H_
    3737
    38 #include <ipc/common.h>
     38#include <async.h>
    3939#include <adt/list.h>
    4040#include <fibril.h>
     41#include <fibril_synch.h>
    4142#include <sys/time.h>
    4243#include <bool.h>
     44
     45/** Session data */
     46struct _async_sess {
     47        /** List of inactive exchanges */
     48        list_t exch_list;
     49       
     50        /** Exchange management style */
     51        exch_mgmt_t mgmt;
     52       
     53        /** Session identification */
     54        int phone;
     55       
     56        /** First clone connection argument */
     57        sysarg_t arg1;
     58       
     59        /** Second clone connection argument */
     60        sysarg_t arg2;
     61       
     62        /** Third clone connection argument */
     63        sysarg_t arg3;
     64       
     65        /** Exchange mutex */
     66        fibril_mutex_t mutex;
     67       
     68        /** Number of opened exchanges */
     69        atomic_t refcnt;
     70       
     71        /** Mutex for stateful connections */
     72        fibril_mutex_t remote_state_mtx;
     73       
     74        /** Data for stateful connections */
     75        void *remote_state_data;
     76};
     77
     78/** Exchange data */
     79struct _async_exch {
     80        /** Link into list of inactive exchanges */
     81        link_t sess_link;
     82       
     83        /** Link into global list of inactive exchanges */
     84        link_t global_link;
     85       
     86        /** Session pointer */
     87        async_sess_t *sess;
     88       
     89        /** Exchange identification */
     90        int phone;
     91};
    4392
    4493/** Structures of this type are used to track the timeout events. */
  • uspace/lib/c/include/async.h

    r921b84f r5fb32c5  
    4242#include <ipc/common.h>
    4343#include <fibril.h>
    44 #include <fibril_synch.h>
    4544#include <sys/time.h>
    4645#include <atomic.h>
     
    9695} exch_mgmt_t;
    9796
    98 /** Session data */
    99 typedef struct {
    100         /** List of inactive exchanges */
    101         list_t exch_list;
    102        
    103         /** Exchange management style */
    104         exch_mgmt_t mgmt;
    105        
    106         /** Session identification */
    107         int phone;
    108        
    109         /** First clone connection argument */
    110         sysarg_t arg1;
    111        
    112         /** Second clone connection argument */
    113         sysarg_t arg2;
    114        
    115         /** Third clone connection argument */
    116         sysarg_t arg3;
    117        
    118         /** Exchange mutex */
    119         fibril_mutex_t mutex;
    120        
    121         /** Number of opened exchanges */
    122         atomic_t refcnt;
    123 } async_sess_t;
    124 
    125 /** Exchange data */
    126 typedef struct {
    127         /** Link into list of inactive exchanges */
    128         link_t sess_link;
    129        
    130         /** Link into global list of inactive exchanges */
    131         link_t global_link;
    132        
    133         /** Session pointer */
    134         async_sess_t *sess;
    135        
    136         /** Exchange identification */
    137         int phone;
    138 } async_exch_t;
     97/** Forward declarations */
     98struct _async_exch;
     99struct _async_sess;
     100
     101typedef struct _async_sess async_sess_t;
     102typedef struct _async_exch async_exch_t;
    139103
    140104extern atomic_t threads_in_ipc_wait;
     
    485449extern int async_state_change_finalize(ipc_callid_t, async_exch_t *);
    486450
     451extern void *async_remote_state_acquire(async_sess_t *);
     452extern void async_remote_state_update(async_sess_t *, void *);
     453extern void async_remote_state_release(async_sess_t *);
     454extern void async_remote_state_release_exchange(async_exch_t *);
     455
    487456#endif
    488457
  • uspace/lib/c/include/ipc/ipc.h

    r921b84f r5fb32c5  
    254254    sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
    255255
    256 extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *,
     256extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, task_id_t *,
    257257    sysarg_t *);
    258258extern int ipc_connect_me(int);
  • uspace/lib/clui/tinput.c

    r921b84f r5fb32c5  
    591591}
    592592
     593/* Print a list of completions */
     594static void tinput_show_completions(tinput_t *ti, char **compl, size_t cnum)
     595{
     596        unsigned int i;
     597        /* Determine the maximum length of the completion in chars */
     598        size_t max_length = 0;
     599        for (i = 0; i < cnum; i++)
     600                max_length = max(max_length, str_length(compl[i]));
     601       
     602        unsigned int cols = max(1, (ti->con_cols + 1) / (max_length + 1));
     603        unsigned int col_width = ti->con_cols / cols;
     604        unsigned int rows = cnum / cols + ((cnum % cols) != 0);
     605       
     606        unsigned int row, col;
     607       
     608        for (row = 0; row < rows; row++) {
     609                bool wlc = false;
     610                for (col = 0; col < cols; col++) {
     611                        size_t compl_idx = col * rows + row;
     612                        if (compl_idx >= cnum)
     613                                break;
     614                        if (col)
     615                                printf(" ");
     616                        printf("%s", compl[compl_idx]);
     617                        size_t compl_len = str_length(compl[compl_idx]);
     618                        if (col == cols -1) {
     619                                wlc = (compl_len == max_length);
     620                        }
     621                        else {
     622                                for (i = compl_len; i < col_width; i++) {
     623                                        printf(" ");
     624                                }
     625                        }
     626                }
     627                if (!wlc) printf("\n");
     628        }
     629}
     630
     631
    593632static void tinput_text_complete(tinput_t *ti)
    594633{
     
    676715
    677716                        tinput_jump_after(ti);
    678                         for (i = 0; i < cnum; i++)
    679                                 printf("%s\n", compl[i]);
     717                        tinput_show_completions(ti, compl, cnum);
    680718                        tinput_display(ti);
    681719                }
Note: See TracChangeset for help on using the changeset viewer.