domingo, 31 de outubro de 2010

Binary Tree made simple

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct bt {
    void *data;
    char *key;
    struct bt *right, *left;
};

/* prototypes */
int add_btnode (struct bt **, char *, void *);
void init_bt (struct bt **);
struct bt *search_btnode (struct bt *, char *);
void print_inorder (struct bt *);

int
main (void)
{
    struct bt *root, *p;
    init_bt (&root);
    add_btnode (&root, "Daniel", "C");
    add_btnode (&root, "Bia", "asm");
    add_btnode (&root, "Nelson", "Php");
    p = search_btnode (root, "Bia");
    printf ("Bia is an %s hacker\n", (char *)p->data);
    puts ("\n\nIN ORDER");
    print_inorder (root);
     
    return 0;
}

void
init_bt (struct bt **r)
{
    *r = NULL;
}

int
add_btnode (struct bt **root, char *k, void *dat)
{
    if (!*root) {
        *root = malloc (sizeof (struct bt));
        if (!*root) exit (EXIT_FAILURE);
        (*root)->key = k;
        (*root)->data = dat;
        (*root)->right = (*root)->left = NULL;
        return 0;
    }    
    if (strcmp (k, (*root)->key) > 0)
        add_btnode (&(*root)->right, k, dat);
    else if (strcmp (k, (*root)->key) < 0)
        add_btnode (&(*root)->left, k, dat);
    return -1;
} 

struct bt *
search_btnode (struct bt *root, char *k)
{
    int rval;
    if (!root) return NULL;
    rval = strcmp (k, root->key);
    while (root && rval) {
        if (rval > 0) root = root->right;
        else root = root->left;
        rval = strcmp (k, root->key);
    }
    return root;
}

void
print_inorder (struct bt *root)
{
    if (!root) return;    
        
    print_inorder (root->left);
    printf ("%s => %s\n", root->key, (char *)root->data);
    print_inorder (root->right);
}


Tested at: http://ideone.com/vL1N0

quinta-feira, 28 de outubro de 2010

Testing Linked List against multiple data types

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct instance {
    int a, b;
    float f;
    char str[8];
    int (*p) (const char *);
};

int
main (void)
{
    llist mylist;
    node *bufnode;
    struct search_result sr;
    int i = -1;
    char string[] = "Hello World";
    float myf = 2.5;
    struct instance strc = {1, 2, 3.4, "Five", puts};
    struct instance otherstrc;

    init_llist (&mylist);

    bufnode = init_node ("struct", (char *)&strc, sizeof (struct instance));
    add_node (&mylist, bufnode);

    bufnode = init_node ("int", (char *)&i, sizeof (int));
    add_node (&mylist, bufnode);

    bufnode = init_node ("string", string, strlen ("Hello World") + 1); 
    add_node (&mylist, bufnode);

    bufnode = init_node ("float", (char *)&myf, sizeof (float));
    add_node (&mylist, bufnode);

    sr = search_node (&mylist, "struct");
    memcpy (&otherstrc, sr.n->data, sizeof (struct instance));
    printf ("otherstrc: %d %d %f %s\n", 
        otherstrc.a, otherstrc.b, otherstrc.f , otherstrc.str);
    otherstrc.p("Nice?");
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "int");
    printf ("%d\n", *(int *)sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "float");
    printf ("%f\n", *(float *)sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "string");
    printf ("%s\n", sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    if (! mylist.first)
        printf ("empty\n");
    return 0;
}


Tested here: http://ideone.com/lTlp9

quarta-feira, 27 de outubro de 2010

How to read an unknown lenght line to a string in C

/*===========================*
 *    Reading dinamically    *
 *===========================*/
#include <stdio.h>
#include <stdlib.h>

#define DATALEN BUFSIZ 

struct block {
    char data[DATALEN];
    struct block *next;
};

struct block *
alloc_block (void)
{
    struct block *new = malloc (sizeof (struct block));
    if (!new) {
        perror ("malloc");
        exit (EXIT_FAILURE);
    }
    return new;
}

int
readfrom (char **str, FILE *stream, int finalchar)
{
    struct block *first;
    struct block *ptr;
    struct block *prev;
    struct block *tmp;
    int ch, indx = 0, nblocks = 1, strindx;

    first = ptr = alloc_block();
    ptr->next = NULL;
    /* read and alloc string as a linked list */
    while ((ch = getc(stream)) != finalchar) {
        if (indx == DATALEN) {
            tmp = alloc_block ();
            indx = 0; 
            nblocks++;
            tmp->next = NULL;
            ptr->next = tmp;
            ptr = tmp;
        } else if (indx > DATALEN) {
            fprintf (stderr, "readline error: Index error\n");
            exit (EXIT_FAILURE);
        }
        ptr->data[indx++] = ch;
    }
    ptr->data[indx] = '\0';
    *str = malloc ( (nblocks - 1) * DATALEN + indx );    
    /* run in list freeing it */
    for 
    (ptr = first, strindx = 0; 
     ptr != NULL; 
     prev = ptr, ptr = ptr->next, free (prev)) 
    {
        for 
        (indx = 0; 
         indx < DATALEN && ptr->data[indx] != '\0'; 
         indx++, strindx++) 
        {
            (*str)[strindx] = ptr->data[indx]; 
        }
    }
    (*str)[strindx] = '\0';
    return strindx;
}

        
int
main (void)
{
    char *str;
    int len;
    len = readfrom (&str, stdin, '\n');
    printf ("Your string with len %d is `%s'\n", len, str);
    return 0;
}

sexta-feira, 22 de outubro de 2010

Layout update

Today I update the blog layout, select a cool space backgroud
and etc. Thanks Google :-)

quinta-feira, 21 de outubro de 2010

The 3 simple sort algorithms

/*    Bubble Sort    */
void
bsort (int ar[], int len)
{
    int control = 1, i, tmp;
    while (control--) {
        for (i = 0; i < len - 1; i++) 
            if (ar[i] > ar[i + 1]) {
                tmp = ar[i], ar[i] = ar[i + 1], ar[i + 1] = tmp;
                control = 1;
            }
    }
}

/*    Inserction Sort    */
void
isort (int ar[], int len)
{
    int i, j, tmp;
    for (i = 1; i < len; i++, ar[j + 1] = tmp) 
        for (j = i -1, tmp = ar[i]; j >= 0 && ar[j] > tmp; j--)
            ar[j + 1] = ar[j];
}

/*    Selection Sort    */
void
ssort (int ar[], int len)
{
    int i, j, lesser, tmp, at;
    for (i = 0; i < len - 1; 
         tmp = ar[i], ar[i] = lesser, ar[at] = tmp, i++)
        for (j = i + 1, lesser = ar[i], at = i; j < len; j++) 
            if (lesser > ar[j]) 
                lesser = ar[j], at = j;
}
tested at http://codepad.org/3Co4Qipn

quarta-feira, 13 de outubro de 2010

gkos Linked List API

The linked list api that I talked about some weeks ago.

I will try to keep it simple, but this was not optimized.


There are 2 files: llapi.h, libllapi.c.

The first you will include in your application as:
#include "llapi.h"
The secont you will use to make an archive.
Do as follow:
gcc -c libllapi.c
ar -rcs libllapi.a libllapi.o


Before to use your list you need to declare and
initialize it.
llist mylist;
init_llist (&mylist);

Ok, now you have a ready to use list, but, what you
may put inside it? The answer is nodes, of course.
Nodes are declared as an struct containing three members:
  • a key for you search it latter
  • a data field with BUFSIZ bytes
  • a pointer to next node
So you need a node buffer, and maybe a data buffer
node *nodebuf;
char data[BUFSIZ];

note: The data buffer need to have BUFSIZ length because the init_node() will try to copy BUFSIZ bytes to node data member. If data buffer has less than BUFSIZ bytes you will recieve a segment fault error at run time, since init_node() will try to dereference an array beyond its boundaries.

You can initialize a node as
nodebuf = init_node ("KeyName", data);
Or you can initialize it by hand. Then, with an initialized
node you can add it in list with:
add_node (&mylist, nodebuf);
After that your node is added in your list. The bufnode will
be set to null, so you can't touch list through it. The maximum number
of nodes is demilited by your avaible memory. The nodes are allocated
inside init_node function. If there is no memory avaible the programm
will exit with a failure status and an error message.

 Since this you may want to free some space, to do this you will need
to delete some nodes. You can delete a node with del_node () function
but you need to know what to delete before to delete. The search_node ()
function is what you want.
struct search_result sr = search_node (&mylist, "keyname");
search_result struct is declared as follow:
struct search_result {
    node *n; 
    node *prior;
};
n points to node that you searched. It will be NULL if your node was not found.
prior is an implementation detail. If the node was found and it's not the first
item in list, prior will point the prior node of n.


Now that you found (or not) your node, sr.n points to it. You can delete it
with the follow statement:
int rval = del_node (&mylist, sr.n, sr.prior); 
The integer rval will hold the return status of del_node () function.
Note that I don't check if my "keyname" was found. The del_node () function
will return BAD_CALL if you call it with 2nd and 3rd arguments as NULL
and will stat if you are trying to delete the first node. The sr.prior member
is used to linking stuff, but you don't need to botter with it, just recieve
from search_node () and pass as it is to del_node () everything is stated
by del_node ().


Here is the two files and an example!

/*
    Copyright 2010 Daniel Hilst Selli    
    
    This file is part of gkos Linked List API.

    gkos Linked List API is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    gkos Linked List API is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser Public License for more details.

    You should have received a copy of the GNU Lesser Public License
    along with gkos Linked List API.  If not, see <http://www.gnu.org/licenses/>.

    Daniel Hilst aka gkos <danielhilst@gmail.com>    
*/

/****************** 
 *    llapi.h     *
 ******************/
#ifndef LLAPI_H
#define LLAPI_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define KEY_SIZ 8
#define EMPTY 0
#define HAS_ONE 1
#define HAS_MORE_THAN_ONE 2
#define ERROR -1
#define BADCALL (ERROR -1)
#define KEY_FOUND_AT_FIRST (struct search_result) {l->first, NULL} 
#define KEY_FOUND            (struct search_result) {np, prior} 
#define KEY_NOT_FOUND            (struct search_result) {NULL, NULL} 

/* data */
typedef struct node {
    struct node *next; 
    char key[KEY_SIZ + 1]; /* +1 to the nil terminator char */
    char *data[BUFSIZ];
} node;

typedef struct llist {
    node *first; /* first item in list */
    node *last;  /* last item in list */
} llist;

struct search_result {
    node *n;
    node *prior;
};


/* prototypes */
void                     add_node     (llist *, node *);
int                     del_node     (llist *, node *, node *);
node                     *init_node     (char *k, char *);
void                     init_llist     (llist *);
struct search_result     search_node    (llist *, char *);

#endif // LLAPI_H



/*
    Copyright 2010 Daniel Hilst Selli    
    
    This file is part of gkos Linked List API.

    gkos Linked List API is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    gkos Linked List API is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser Public License for more details.

    You should have received a copy of the GNU Lesser Public License
    along with gkos Linked List API.  If not, see <http://www.gnu.org/licenses/>.

    Daniel Hilst aka gkos <danielhilst@gmail.com>    
*/
/********************** 
 *     libllapi.c     * 
 **********************/
#include "llapi.h"
#define PRIVATE static

/* internal prototypes */
PRIVATE node *alloc_node (void);
PRIVATE int isempty (llist *);


/* interface */

void
add_node (llist *l, node *n)
{
    int rval = isempty (l);
    if (rval == EMPTY) {
        l->first = l->last = n;
    } else if (rval == HAS_ONE) {
        l->first->next = n;
        l->last = n;    
    } else if (rval == HAS_MORE_THAN_ONE) {
        l->last->next = n;
        l->last = n;
    } else {
        perror ("isempty");
        exit (EXIT_FAILURE);
    }
    n = NULL; /* so peopple can't touch list directly */
}

int
del_node (llist *l, node *n, node *prior)
{
    int rval = isempty (l);
    if (rval == HAS_ONE) {
        init_llist (l); /* set list as empty again */
        free (n);
    } else if (rval == HAS_MORE_THAN_ONE) {
        if (n == l->first) {
            l->first = l->first->next;
            free (n); /* or free (l->first) */        
        } else if (n == l->last) {
            l->last = prior;
            l->last->next = NULL;
            free (n); /* or free the ex last */
        } else {
            prior->next = prior->next->next; /* link over n */
            free (n);
        }
    } else if (rval == EMPTY) { /* the list is empty */ 
        return BADCALL;
    } else {
        return ERROR;
    }
    return 0;
}

void
init_llist (llist *l)
{
    l->first = l->last = NULL;    
}

node * 
init_node (char *k, char *data)
{
    /* alloc new node */
    node *new = alloc_node ();
    /* set next */
    new->next = NULL;
    /* set key */
    strncpy (new->key, k, KEY_SIZ); 
    new->key[KEY_SIZ] = '\0';
    /* set data */
    memcpy (new->data, data, BUFSIZ);
    /* return the new initalized node */
    return new;
}


struct search_result
search_node (llist *l, char *k)
{
    struct node *np, *prior;
    if (strlen (k) > KEY_SIZ) {
        k[KEY_SIZ] = '\0';
    }
    if (strcmp (l->first->key, k) == 0) {
        return (struct search_result) KEY_FOUND_AT_FIRST; /* (struct search_result) {l->first, NULL} */
    } else {
        for (np = l->first->next, prior = l->first; np != NULL; np = np->next) {
            if (strcmp (np->key, k) == 0) {
                return KEY_FOUND; /* (struct search_result) {np, prior} */ 
            }
            prior = prior->next;
        }
        return KEY_NOT_FOUND; /* (struct search_result) {NULL, NULL} */
    }
    
}


/* internals */ 

PRIVATE int 
isempty (llist *l)
{
    if (l->first == NULL && l->last == NULL)
        return EMPTY;
    else if (l->first == l->last)
        return HAS_ONE;
    else if (l->first->next != NULL)
        return HAS_MORE_THAN_ONE; 
    else 
        return ERROR;
}

PRIVATE node *
alloc_node (void)
{
    node *new = malloc (sizeof (node));
    if (new == NULL) {
        perror ("malloc");
        exit (EXIT_FAILURE);
    }
    return new;
}



#include <stdio.h>
#include "llapi.h"

int
main (void)
{
    int i;
    llist mylist;
    node *bufnode;
    char databuffer[BUFSIZ];
    memcpy (databuffer, "Daniel Hilst", strlen ("Daniel Hilst") + 1);
    struct search_result sr;
    init_llist (&mylist);

    bufnode = init_node ("name", databuffer);    
    add_node (&mylist, bufnode);

    bufnode = init_node ("myname", databuffer);    
    add_node (&mylist, bufnode);

    bufnode = init_node ("thename", databuffer);    
    add_node (&mylist, bufnode);
    
    bufnode = init_node ("onwname", databuffer);    
    add_node (&mylist, bufnode);

    sr = search_node (&mylist, "thename");
    printf ("%s => %s\n", sr.n->key, sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "myname");
    printf ("%s => %s\n", sr.n->key, sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "onwname");
    printf ("%s => %s\n", sr.n->key, sr.n->data);
    del_node (&mylist, sr.n, sr.prior);

    sr = search_node (&mylist, "name");    
    printf ("%s => %s\n", sr.n->key, sr.n->data);
    del_node (&mylist, sr.n, sr.prior);
    return 0;
}


This would print:
thename => Daniel Hilst
myname => Daniel Hilst
onwname => Daniel Hilst
name => Daniel Hilst



*edit
I create a git repository to this. It's easier to update stuff with git... 
there you'll find an updated README.
http://github.com/gkos/gko-s-Linked-List



cheers! :-)

terça-feira, 12 de outubro de 2010

optimizing example

/*
 * #include <stdio.h>
 * 
 * int
 * main (void)
 * {
 *     int i;    
 *     for (i = 0; i < 10; i++)
 *         printf ("%d ", i);
 *     return 0;
 * }
 */
    .file    "ex.c"
    .section    .rodata
.LC0:
    .string    "%d "
    .text
.globl main
    .type    main, @function
main:
    pushl    %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $0, 28(%esp)
    jmp    .L2
.L3:
    movl    $.LC0, %eax
    movl    28(%esp), %edx
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    addl    $1, 28(%esp)
.L2:
    cmpl    $9, 28(%esp)
    jle    .L3
    movl    $0, %eax
    leave
    ret
    .size    main, .-main
    .ident    "GCC: (GNU) 4.5.1"
    .section    .note.GNU-stack,"",@progbits

.file    "ex.c"
    .section    .rodata
.LC0:
    .string    "%d "
    .text
.globl main
    .type    main, @function
main:
    pushl    %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $0, 4(%esp)
    jmp    .L2
.L3:
    movl    $.LC0, %eax
    movl    %eax, (%esp)
    call    printf
    incl    4(%esp)
.L2:
    cmpl    $9, 4(%esp)
    jle    .L3
    movl    $0, %eax
    leave
    ret
    .size    main, .-main
    .ident    "GCC: (GNU) 4.5.1"
    .section    .note.GNU-stack,"",@progbits
The first file has as comment the c program that generates it.
The second one is the same, but with some modifications that I made..
reducing the number of instructions and replacing an add
with an inc intruction. Assembly world is really fun!!

Oh yes.. I extend SH to get a poorly gas syntaxhighlighter (:
I guess this is my first real work with free community!!
here is the post announcement: http://alexgorbatchev.com/forums/viewtopic.php?f=2&t=77 and
here is the project page http://github.com/gkos/gas-brush
I'm felling really happy with this!! Maybe tomorrow I speak about downseq project (:

Cheers!

domingo, 10 de outubro de 2010

another hello world in gas, this time calling puts from libc

# another hello world example
# you can compile this like:
# $ as -o hw.o mainhw.s 
# $ gcc -o hw hw.o -lc
# $ ./hw
#
    .file "mainhw.s"
    .section .rodata 
.Lstr:                       # the address of our string
    .asciz "Hello, World"

    .text
    .type main, @function
    .globl main
main:
    pushl %ebp              # prologue of every function
    movl %esp, %ebp         # still prologue.. 
    pushl $.Lstr            # pass arguments on stack
    call puts               # puts(.Lstr)
    movl $0, %eax           # the 0 of return 0
    leave                   # epilogue of every function
    ret                     # return 
    .size main, . - main    

sábado, 9 de outubro de 2010

gas copy string n ;-)

#
# void
# mycpynstr (char *dst, char *src, int n)
# {
#     while (n--)
#         *dst++ = *src++;
# }
#
    .file    "cpystr.c"
    .text
.globl mycpynstr
    .type    cpynstr, @function
mycpynstr:
    pushl    %ebp
    movl    %esp, %ebp
    jmp    .L2             # goto (.L2)

#   *dst++ = *src++ at line 6
.L3:
    movl    12(%ebp), %eax #     move src to %eax  
    movzbl    (%eax), %edx #     %dl = (char *) %eax # (src) 
    movl    8(%ebp), %eax  #     move dst to %eax
    movb    %dl, (%eax)    #     *dst = *src
    addl    $1, 8(%ebp)    #     src++ 
    addl    $1, 12(%ebp)   #     dst++ 

# while (n--) at line 5
.L2:
    cmpl    $0, 16(%ebp)   #   if (n != 0) 
    setne    %al           #     %al = 1
    subl    $1, 16(%ebp)   #   n--
    testb    %al, %al      #   if (%al)    
    jne    .L3             #     goto (.L3)
    popl    %ebp           #   else
    ret                    #     return

    .size    mycpynstr, .-mycpynstr
    .ident    "GCC: (GNU) 4.5.1"
    .section    .note.GNU-stack,"",@progbits
I made this with `gcc -S cpystr.c' where cpystr.c contains the mycpynfunction
defined as in first eight lines in this file. Then I open the file cpystr.s
created by gcc and add the coments. Nothing more was changed.
The comments tell in C language what is happening. But I not sure if
every comment is exactly right... its just how I understand the code. The
comments start with `#' character and extends to the end of line.
Cheers :-)

sexta-feira, 8 de outubro de 2010

gas hello wolrd

.text
.global _start
_start:
    movl $4, %eax
    movl $1, %ebx
    movl $str, %ecx
    movl $len, %edx
    int  $0x80

    movl $1, %eax
    xor  %ebx, %ebx
    int  $0x80

.data

str:
    .ascii "Hello World" 
    .set len, . - str

quarta-feira, 6 de outubro de 2010

Java looks handy

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.*;
import javax.swing.*;

class GHelloWorld extends JFrame
  implements ActionListener{
 Container cp;
 JLabel lb;
 JButton bt;
 
 public GHelloWorld( ) {
  cp =  this.getContentPane( ); 
  cp.setLayout(new FlowLayout( )); 
  lb = new JLabel("Hello World");
  cp.add(lb);
  bt = new JButton ("Hi, there!");
  bt.addActionListener(this);
  cp.add(bt);
 }
 
 public void actionPerformed(ActionEvent e) {
  System.out.println("Hello World");
  System.exit(0);
 } 

 static public void main (String[ ] args) {
  GHelloWorld cf = new  GHelloWorld( );
  cf.setTitle("Hello World");
  cf.setSize(400,300);
  cf.setVisible(true);
 }
} 

A gui hello world example.. I really like the ideia
of code once and distribute it for every one on
almost all systems. I read
(3 days reading) and like it. I need more time to get used with gui API and
a little bit of pratice. I do not intend to become a java programer, I love C, C is everything!!
But java is really handy, really really handy. (:
I want to translante this to java
Yes I do this in python.. First in shell, than python.. and now I want it in java with gui and
friendly manage.