void cmd_build_list(queue_t *qb,char *buf) { char *cur = buf, *start = NULL, *fin = NULL; ui_token_t *t; q_init(qb); start = cur; while(*cur != '\0'){ if (*cur == '&' && *(cur + 1) != '&') { /* Do nothing if we have only one & */ } else if (*cur == '|' && *(cur + 1) != '|') { /* Do nothing if we have only one | */ } else if (((*cur == ' ')||(*cur == '\t')) && ((*(cur - 1) == ' ')||(*(cur - 1) == '\t'))) { /* Make one big token for white space */ } else { if (strchr(tokenbreaks,*cur)) { if (cur != buf) { fin = cur; t = make_token(start,fin-start); q_enqueue(qb,&(t->qb)); start = cur; /* Start new token */ } } else { /* If we are on a normal character but the last character was */ /* a special char we need to start a new token */ if ((cur > buf) && strchr(tokenbreaks,*(cur-1))) { fin = cur; t = make_token(start,fin-start); q_enqueue(qb,&(t->qb)); start = cur; /* Start new token */ } else { /* If the last charecter wasn't special keep going with */ /* current token */ } } } cur++; } fin = cur; if (fin-start > 0) { t = make_token(start,fin-start); q_enqueue(qb,&(t->qb)); } return; }
void cmd_walk_and_expand (queue_t *qb) { queue_t *q; queue_t newq; ui_token_t *t; int alias_check = TRUE; int insquote = FALSE; char *envstr; q_init(&newq); while ((t = (ui_token_t *) q_deqnext(qb))) { if (t->token == '\'') { alias_check = FALSE; insquote = !insquote; /* Check to see if we should try to expand this token */ } else if (!insquote) { if (alias_check && !strchr(tokenbreaks,t->token) && (envstr = env_getenv(&(t->token)))) { /* Aliases: stick into token stream if no environment found */ cmd_append_tokens(&newq,envstr); KFREE(t); t = NULL; } else if (t->token == '$') { /* non-aliases: remove from token stream if no env found */ envstr = env_getenv(&(t->token)+1); if (envstr) cmd_append_tokens(&newq,envstr); KFREE(t); t = NULL; } else { /* Drop down below, keep this token as-is and append */ } } /* * If token was not removed, add it to the new queue */ if (t) { q_enqueue(&newq,&(t->qb)); alias_check = is_command_separator(t); } } /* * Put everything back on the original list. */ while ((q = q_deqnext(&newq))) { q_enqueue(qb,q); } }
} END_TEST START_TEST(check_queue_size) { Job job1, job2; Queue *q = new_queue(); assert_equal(0, q_size(q)); q_enqueue(q, &job1); assert_equal(1, q_size(q)); q_enqueue(q, &job2); assert_equal(2, q_size(q)); free_queue(q); } END_TEST
static void test_q_dequeue(void) { Queue* q = q_new(); int first; int status = q_enqueue(q, &first); int second; status = q_enqueue(q, &second); CU_ASSERT_PTR_EQUAL(q_dequeue(q), &first); CU_ASSERT_EQUAL(q_size(q), 1); CU_ASSERT_PTR_EQUAL(q_dequeue(q), &second); CU_ASSERT_EQUAL(q_size(q), 0); q_free(q); }
int cfe_attach_idx(cfe_driver_t *drv,int idx,void *softc, char *bootinfo,char *description) { char name[64]; cfe_device_t *dev; xsprintf(name,"%s%d",drv->drv_bootname,idx); if (bootinfo) { strcat(name,"."); strcat(name,bootinfo); } if (cfe_finddev(name) != NULL) { return 0; } dev = (cfe_device_t *) KMALLOC(sizeof(cfe_device_t),0); if (!dev) return -1; dev->dev_fullname = strdup(name); dev->dev_softc = softc; dev->dev_class = drv->drv_class; dev->dev_dispatch = drv->drv_dispatch; dev->dev_description = description ? strdup(description) : NULL; dev->dev_opencount = 0; q_enqueue(&cfe_devices,(queue_t *) dev); return 1; }
void uart_transmit(const char *data, ...) { // char buf[MAX_BUFF_SIZE]; unsigned int i = 0; int num_read = 0; /* Way to read the formated string as the argument */ va_list args; va_start(args, data); num_read = vsprintf(buf, data, args); /* Write the data given as an arugment to the queue */ while(i < num_read && i < MAX_BUFF_SIZE) { if(!q_full(&TxQ)){ q_enqueue(&TxQ, buf[i]); i++; }else{ /* Don't increment the iterator, try to insert the data in the next run */ } } /* Each time you insert something, make sure that the interrupt fot transmitter is active */ UART0->C2 |= UART0_C2_TIE_MASK; va_end(args); }
} END_TEST START_TEST (multiple_items) { Job job1, job2; Queue *q = new_queue(); assert_not_null(q); q_enqueue(q, &job1); q_enqueue(q, &job2); assert_false(q_empty(q)); Job *d_job1 = q_dequeue(q); Job *d_job2 = q_dequeue(q); assert_equal(&job1, d_job1); assert_equal(&job2, d_job2); free_queue(q); } END_TEST
void process(int vi, int* dist, queue* pq, bool* isInQueue, long long* thisLoopCount, long long* thisUpdateCount) { adj_node* vj_p = adj_listhead[vi]; // Loop over edges out of vi while(vj_p) { int vj = vj_p -> vertex; int newdist_vj; bool needToUpdate; // Do this if new distance is smaller // #pragma omp critical(dist) { newdist_vj = dist[vi] + vj_p->weight;// new distance throught vi needToUpdate = (newdist_vj < dist[vj]) || (dist[vj] == INF); } (*thisLoopCount)++; { if(needToUpdate) { // #pragma omp critical(dist) (*thisUpdateCount)++; dist[vj] = newdist_vj; // #pragma omp critical(queue) if(isInQueue[vj] == false) { q_enqueue(vj, pq); isInQueue[vj] = true; } } vj_p = vj_p -> next; } } }
int env_setenv(const char *name,char *value,int flags) { cfe_envvar_t *env; int namelen; env = env_findenv(name); if (env) { if (!(flags & ENV_FLG_ADMIN)) { if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY; } q_dequeue((queue_t *) env); KFREE(env); } namelen = strlen(name); env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0); if (!env) return CFE_ERR_NOMEM; env->name = (char *) (env+1); env->value = env->name + namelen + 1; env->flags = (flags & ENV_FLG_MASK); strcpy(env->name,name); strcpy(env->value,value); q_enqueue(&env_envvars,(queue_t *) env); return 0; }
ui_command_t *cmd_readcommand(queue_t *head) { char *ptr; int insquote = FALSE; int indquote = FALSE; ui_command_t *cmd; int term = CMD_TERM_EOL; ui_token_t *t; cmd_eat_leading_white(head); if (q_isempty(head)) return NULL; cmd = (ui_command_t *) KMALLOC(sizeof(ui_command_t),0); q_init(&(cmd->head)); while ((t = (ui_token_t *) q_deqnext(head))) { ptr = &(t->token); if (!insquote && !indquote) { if ((*ptr == ';') || (*ptr == '\n')) { term = CMD_TERM_SEMI; break; } if ((*ptr == '&') && (*(ptr+1) == '&')) { term = CMD_TERM_AND; break; } if ((*ptr == '|') && (*(ptr+1) == '|')) { term = CMD_TERM_OR; break; } } if (*ptr == '\'') { insquote = !insquote; } if (!insquote) { if (*ptr == '"') { indquote = !indquote; } } q_enqueue(&(cmd->head),&(t->qb)); } cmd->term = term; /* If we got out by finding a command separator, eat the separator */ if (term != CMD_TERM_EOL) { KFREE(t); } return cmd; }
} END_TEST START_TEST (single_item) { Job job; Queue *q = new_queue(); assert_not_null(q); q_enqueue(q, &job); Job *d_job = q_dequeue(q); assert_equal(&job, d_job); free_queue(q); } END_TEST
static void cmd_append_tokens(queue_t *qb,char *str) { queue_t *qq; queue_t explist; cmd_build_list(&explist,str); while ((qq = q_deqnext(&explist))) { q_enqueue(qb,qq); } }
int check_queue() { QUEUE *queue; char *item; size_t counter; queue = q_init(); if(!queue) { fprintf(stderr, "unable to initialize queue\n"); return 0; } for(counter = 0; datas[counter]; counter ++) q_enqueue(queue, datas[counter], strlen(datas[counter]) + 1); item = (char *)q_front(queue); if(!item) { fprintf(stderr, "got NULL when expecting %s\n", datas[counter]); return 1; } if(strcmp(item, datas[0])) { fprintf(stderr, "q_front() returned %s, expecting %s\n", item, datas[0]); return 2; } for(counter = 0; datas[counter]; counter ++) { item = (char *)q_dequeue(queue); if(!item || strcmp(item, datas[counter])) { fprintf(stderr, "got %s, expecting %s\n", item, datas[counter]); return 3; } free(item); } item = (char *)q_dequeue(queue); if(item) { fprintf(stderr, "got %s when expecting NULL\n", item); return 4; } q_free(queue, QUEUE_NODEALLOC); return 0; }
static void console_save(unsigned char *buffer,int length) { msgqueue_t *msg; /* * Get a pointer to the last message in the queue. If * it's full, preprare to allocate a new one */ msg = (msgqueue_t *) console_msgq.q_prev; if (q_isempty(&(console_msgq)) || (msg->len == MSGQUEUESIZE)) { msg = NULL; } /* * Stuff characters into message chunks till we're done */ while (length) { /* * New chunk */ if (msg == NULL) { msg = (msgqueue_t *) KMALLOC(sizeof(msgqueue_t),0); if (msg == NULL) return; msg->len = 0; q_enqueue(&console_msgq,(queue_t *) msg); /* * Remove chunks to prevent chewing too much memory */ while (q_count(&console_msgq) > MSGQUEUEMAX) { msgqueue_t *dropmsg; dropmsg = (msgqueue_t *) q_deqnext(&console_msgq); if (dropmsg) KFREE(dropmsg); } } /* * Save text. If we run off the end of the buffer, prepare * to allocate a new one */ msg->data[msg->len++] = *buffer++; length--; if (msg->len == MSGQUEUESIZE) msg = NULL; } }
void sequence(chatmessage_t* message, packet_t* newpacket) { message->seqnum = atoi(newpacket->packetbody); remove_elem(UNSEQ_CHAT_MSGS,(void*)message); q_enqueue(HBACK_Q,(void*)message); chatmessage_t* firstmessage = (chatmessage_t*)q_peek(HBACK_Q); pthread_mutex_lock(&seqno_mutex); if(firstmessage->messagetype == JOIN && SEQ_NO == -1) //my first message to display! { SEQ_NO = firstmessage->seqnum; } if(firstmessage->seqnum > SEQ_NO) { printf("SEQUENCE OUT OF SYNC. Skipping Ahead by %d messages\n",firstmessage->seqnum-SEQ_NO); SEQ_NO = firstmessage->seqnum; } if(firstmessage->seqnum <= SEQ_NO) { SEQ_NO = firstmessage->seqnum + 1; client_t* firstclientmatchbyname; if(firstmessage->messagetype == CHAT) { // printf("\E[34m%s\E(B\E[m (sequenced: %d):\t%s\n", firstmessage->sender, firstmessage->seqnum,firstmessage->messagebody); firstclientmatchbyname = find_client_by_uid(firstmessage->senderuid); } else { // printf("\E[34m%s\E(B\E[m joined the chat (sequenced: %d)\n", firstmessage->messagebody, firstmessage->seqnum); firstclientmatchbyname = find_client_by_uid(firstmessage->senderuid); } char* uid = ""; if(firstclientmatchbyname != NULL) { uid = firstclientmatchbyname->uid; remove_elem(UNSEQ_CHAT_MSGS,firstmessage); } if(firstmessage->messagetype == CHAT) print_msg_with_senderids(firstmessage->sender,firstmessage->messagebody, uid); q_dequeue(HBACK_Q); } pthread_mutex_unlock(&seqno_mutex); return; }
void test_q() { printf("\ntesting queue\n"); int capacity = 128; struct qnode* q = q_create(capacity); int num = 200; for (int i = 0; i < num; ++i) { q_enqueue(q, i); } while (!q_empty(q)) { printf("%d ", q_dequeue(q)); } q_destroy(q); }
void UART0_IRQHandler(void) { NVIC_ClearPendingIRQ(UART0_IRQn); /* Transmitter part */ if(UART0->S1 & UART_S1_TDRE_MASK) { if(!q_empty(&TxQ)){ // there is something to transmit UART0->D = q_dequeue(&TxQ); }else{ // there is nothing to transmit UART0->C2 &= ~UART_C2_TIE_MASK; // clear the interrupt flag } } /* Receiver part */ if(UART0->S1 & UART_S1_RDRF_MASK) { if(!q_full(&RxQ)){ // there is still space to store something q_enqueue(&RxQ, UART0->D); }else{ // error - receiver queue full while(1); } } }
/* Mete un nuevo cliente en el servidor * * PRE: ta == tiempo (absoluto) de arribo del cliente al sistema * CASE1: !busy * CASE2: busy * * accepted = receive_customer (q, ta, &busy, &tsal) * * POS: !accepted => servidor lleno, cliente rechazado * * accepted && CASE1 => el servidor estaba vacio, atendimos al cliente * *tsal contiene el proximo tiempo (abs) de salida * * accepted && CASE2 => el servidor estaba ocupado, cliente puesto en cola * *tsal no fue modificado */ static bool receive_customer (queue_t q, double ta, bool *busy, double *tsal) { bool accepted = true; if (q_is_full(q)) /* Servidor lleno => se descarta al cliente */ accepted = false; else { q_enqueue (q, ta); if (!(*busy)) { /* Servidor vacío => se atiende al cliente directamente */ *tsal = ta + gen_exp (Ts); *busy = true; } /* else: Servidor ocupado => sólo encolabamos al cliente */ } return accepted; }
int moore(int source) { // distance between source vertex and current vertex int* dist; queue q; bool* isInQueue; long long thisLoopCount = 0, thisUpdateCount = 0; // Initialize dist =(int *) malloc((N+1) * sizeof(int)); isInQueue =(bool *) malloc((N+1) * sizeof(bool)); for(int i = 1; i <= N; i++) dist[i] = INF; for(int i = 1; i <= N; i++) isInQueue[i] = false; q_init(&q); dist[source] = 0; isInQueue[source] = true; q_enqueue(source, &q); // Loop over entries in queue // #pragma omp parallel shared(dist, adj_listhead, q) // #pragma omp single while(!q_isEmpty(&q)) { int vi; // #pragma omp critical(queue) vi = q_dequeue(&q); isInQueue[vi] = false; // #pragma omp task { process(vi, dist, &q, isInQueue, &thisLoopCount, &thisUpdateCount); } } // All done // implicit barrier // all tasks should be finished below this line if(DEBUG) { printf("source = %d, ", source); printf("%d %d %d", dist[1], dist[N-1], dist[N]); printf("\n"); } free(dist); free(isInQueue); loopCount[omp_get_thread_num()] += thisLoopCount; updateCount[omp_get_thread_num()] += thisUpdateCount; }
static void DFLOWworker(void *T) { struct worker *t = (struct worker *) T; DataFlow flow; FlowEvent fe = 0, fnxt = 0; int id = (int) (t - workers); Thread thr; str error = 0; int i,last; Client cntxt; InstrPtr p; thr = THRnew("DFLOWworker"); GDKsetbuf(GDKmalloc(GDKMAXERRLEN)); /* where to leave errors */ GDKerrbuf[0] = 0; MT_lock_set(&dataflowLock, "DFLOWworker"); cntxt = t->cntxt; MT_lock_unset(&dataflowLock, "DFLOWworker"); if (cntxt) { /* wait until we are allowed to start working */ MT_sema_down(&t->s, "DFLOWworker"); } while (1) { if (fnxt == 0) { MT_lock_set(&dataflowLock, "DFLOWworker"); cntxt = t->cntxt; MT_lock_unset(&dataflowLock, "DFLOWworker"); fe = q_dequeue(todo, cntxt); if (fe == NULL) { if (cntxt) { /* we're not done yet with work for the current * client (as far as we know), so give up the CPU * and let the scheduler enter some more work, but * first compensate for the down we did in * dequeue */ MT_sema_up(&todo->s, "DFLOWworker"); MT_sleep_ms(1); continue; } /* no more work to be done: exit */ break; } } else fe = fnxt; if (ATOMIC_GET(exiting, exitingLock, "DFLOWworker")) { break; } fnxt = 0; assert(fe); flow = fe->flow; assert(flow); /* whenever we have a (concurrent) error, skip it */ if (flow->error) { q_enqueue(flow->done, fe); continue; } /* skip all instructions when we have encontered an error */ if (flow->error == 0) { #ifdef USE_MAL_ADMISSION if (MALadmission(fe->argclaim, fe->hotclaim)) { fe->hotclaim = 0; /* don't assume priority anymore */ if (todo->last == 0) MT_sleep_ms(DELAYUNIT); q_requeue(todo, fe); continue; } #endif error = runMALsequence(flow->cntxt, flow->mb, fe->pc, fe->pc + 1, flow->stk, 0, 0); PARDEBUG fprintf(stderr, "#executed pc= %d wrk= %d claim= " LLFMT "," LLFMT " %s\n", fe->pc, id, fe->argclaim, fe->hotclaim, error ? error : ""); #ifdef USE_MAL_ADMISSION /* release the memory claim */ MALadmission(-fe->argclaim, -fe->hotclaim); #endif /* update the numa information. keep the thread-id producing the value */ p= getInstrPtr(flow->mb,fe->pc); for( i = 0; i < p->argc; i++) flow->mb->var[getArg(p,i)]->worker = thr->tid; MT_lock_set(&flow->flowlock, "DFLOWworker"); fe->state = DFLOWwrapup; MT_lock_unset(&flow->flowlock, "DFLOWworker"); if (error) { MT_lock_set(&flow->flowlock, "DFLOWworker"); /* only collect one error (from one thread, needed for stable testing) */ if (!flow->error) flow->error = error; MT_lock_unset(&flow->flowlock, "DFLOWworker"); /* after an error we skip the rest of the block */ q_enqueue(flow->done, fe); continue; } } /* see if you can find an eligible instruction that uses the * result just produced. Then we can continue with it right away. * We are just looking forward for the last block, which means we * are safe from concurrent actions. No other thread can steal it, * because we hold the logical lock. * All eligible instructions are queued */ #ifdef USE_MAL_ADMISSION { InstrPtr p = getInstrPtr(flow->mb, fe->pc); assert(p); fe->hotclaim = 0; for (i = 0; i < p->retc; i++) fe->hotclaim += getMemoryClaim(flow->mb, flow->stk, p, i, FALSE); } #endif MT_lock_set(&flow->flowlock, "DFLOWworker"); for (last = fe->pc - flow->start; last >= 0 && (i = flow->nodes[last]) > 0; last = flow->edges[last]) if (flow->status[i].state == DFLOWpending && flow->status[i].blocks == 1) { flow->status[i].state = DFLOWrunning; flow->status[i].blocks = 0; flow->status[i].hotclaim = fe->hotclaim; flow->status[i].argclaim += fe->hotclaim; fnxt = flow->status + i; break; } MT_lock_unset(&flow->flowlock, "DFLOWworker"); q_enqueue(flow->done, fe); if ( fnxt == 0) { int last; MT_lock_set(&todo->l, "DFLOWworker"); last = todo->last; MT_lock_unset(&todo->l, "DFLOWworker"); if (last == 0) profilerHeartbeatEvent("wait", 0); } } GDKfree(GDKerrbuf); GDKsetbuf(0); THRdel(thr); MT_lock_set(&dataflowLock, "DFLOWworker"); t->flag = EXITED; MT_lock_unset(&dataflowLock, "DFLOWworker"); }
/*! \fn void x_enqueue(struct Dequeue *queue, void *data) * \brief enqueues data into the queue <br/> * <b> Precondition : The queue should have been initialized</b> <br/> * <b> Postcondition : The data is added into the queue</b> <br/> * \param queue The queue to which data is being added * \param data The data which is being added to the queue * \return Nothing */ void x_enqueue(struct Dequeue *queue, void *data) { q_enqueue(queue->queue,data,queue->size_of_data); }
static str DFLOWscheduler(DataFlow flow, struct worker *w) { int last; int i; #ifdef USE_MAL_ADMISSION int j; InstrPtr p; #endif int tasks=0, actions; str ret = MAL_SUCCEED; FlowEvent fe, f = 0; if (flow == NULL) throw(MAL, "dataflow", "DFLOWscheduler(): Called with flow == NULL"); actions = flow->stop - flow->start; if (actions == 0) throw(MAL, "dataflow", "Empty dataflow block"); /* initialize the eligible statements */ fe = flow->status; MT_lock_set(&flow->flowlock, "DFLOWscheduler"); for (i = 0; i < actions; i++) if (fe[i].blocks == 0) { #ifdef USE_MAL_ADMISSION p = getInstrPtr(flow->mb,fe[i].pc); if (p == NULL) { MT_lock_unset(&flow->flowlock, "DFLOWscheduler"); throw(MAL, "dataflow", "DFLOWscheduler(): getInstrPtr(flow->mb,fe[i].pc) returned NULL"); } for (j = p->retc; j < p->argc; j++) fe[i].argclaim = getMemoryClaim(fe[0].flow->mb, fe[0].flow->stk, p, j, FALSE); #endif q_enqueue(todo, flow->status + i); flow->status[i].state = DFLOWrunning; PARDEBUG fprintf(stderr, "#enqueue pc=%d claim=" LLFMT "\n", flow->status[i].pc, flow->status[i].argclaim); } MT_lock_unset(&flow->flowlock, "DFLOWscheduler"); MT_sema_up(&w->s, "DFLOWscheduler"); PARDEBUG fprintf(stderr, "#run %d instructions in dataflow block\n", actions); while (actions != tasks ) { f = q_dequeue(flow->done, NULL); if (ATOMIC_GET(exiting, exitingLock, "DFLOWscheduler")) break; if (f == NULL) throw(MAL, "dataflow", "DFLOWscheduler(): q_dequeue(flow->done) returned NULL"); /* * When an instruction is finished we have to reduce the blocked * counter for all dependent instructions. for those where it * drops to zero we can scheduler it we do it here instead of the scheduler */ MT_lock_set(&flow->flowlock, "DFLOWscheduler"); tasks++; for (last = f->pc - flow->start; last >= 0 && (i = flow->nodes[last]) > 0; last = flow->edges[last]) if (flow->status[i].state == DFLOWpending) { flow->status[i].argclaim += f->hotclaim; if (flow->status[i].blocks == 1 ) { flow->status[i].state = DFLOWrunning; flow->status[i].blocks--; q_enqueue(todo, flow->status + i); PARDEBUG fprintf(stderr, "#enqueue pc=%d claim= " LLFMT "\n", flow->status[i].pc, flow->status[i].argclaim); } else { flow->status[i].blocks--; } } MT_lock_unset(&flow->flowlock, "DFLOWscheduler"); } /* release the worker from its specific task (turn it into a * generic worker) */ MT_lock_set(&dataflowLock, "DFLOWscheduler"); w->cntxt = NULL; MT_lock_unset(&dataflowLock, "DFLOWscheduler"); /* wrap up errors */ assert(flow->done->last == 0); if (flow->error ) { PARDEBUG fprintf(stderr, "#errors encountered %s ", flow->error ? flow->error : "unknown"); ret = flow->error; } return ret; }
static char *cmd_eat_quoted_arg(queue_t *head,ui_token_t *t) { int dquote = 0; int squote = 0; queue_t qlist; queue_t *q; char *dest; int maxlen = 0; /* * If it's not a quoted string, just return this token. */ if (!myisquote(t->token)) { dest = lib_strdup(&(t->token)); /* Note: caller deletes original token */ return dest; } /* * Otherwise, eat tokens in the quotes. */ q_init(&qlist); if (t->token == '"') dquote = 1; else squote = 1; /* must be one or the other */ t = (ui_token_t *) q_deqnext(head); while (t != NULL) { /* A single quote can only be terminated by another single quote */ if (squote && (t->token == '\'')) { KFREE(t); break; } /* A double quote is only honored if not in a single quote */ if (dquote && !squote && (t->token == '\"')) { KFREE(t); break; } /* Otherwise, keep this token. */ q_enqueue(&qlist,(queue_t *) t); t = (ui_token_t *) q_deqnext(head); } /* * Go back through what we collected and figure out the string length. */ for (q = qlist.q_next; q != &qlist; q = q->q_next) { maxlen += strlen(&(((ui_token_t *) q)->token)); } dest = KMALLOC(maxlen+1,0); if (!dest) return NULL; *dest = '\0'; while ((t = (ui_token_t *) q_deqnext(&qlist))) { strcat(dest,&(t->token)); KFREE(t); } return dest; }