Thursday, April 7, 2011

BrainForce

A definição da linguagem:

Acabo de criar uma linguagem, chamada de BrainForce, desenvolvida baseada nas definições da linguagem de Urban Muller.

A linguagem basicamente tem 8 comandos:

  1. '+' : adiciona um à célula na posição do ponteiro
  2. '-' : subtrai um da céluna na posição do ponteiro
  3. '>' : move o ponteiro para a direita uma casa
  4. '<' : move o ponteiro para a esquerda uma casa
  5. '[' : inicia um laço se o valor na posição do ponteiro for diferente de zero, pula o laço caso contrário
  6. ']' : fecha o laço, retornando o controle para o colchete respectivo que o abriu
  7. '.' : imprime um valor na saída padrão
  8. ',' : lê um valor da entrada padrão
Além desses comandos, é possível utilizar um comando de debug '#' que permite imprimir de uma só vez o valor de cada uma das dez primeiras células (na versão 2.0, isso será variável, imprimindo os 11 valores centrados no ponteiro, 5 a sua esquerda e 5 a sua direita, além do próprio).

Nos comentários do arquivo de definição do analisador léxico se encontram essas explicações (o programa foi todo codificado em inglês, para melhor aceitação da comunidade internacional, incluindo comentários e nomes de variáveis):
/*
BrainForce Compiler v.1.0, An esoteric programming language
Author: Ruben Carlo Benante (Dr. Beco)
Email: rcb [at] beco.cc
Creation date: 05/Apr/2011
Project based on the ideas of Urban Muller (http://fi.aminet.net/dev/lang)
WebPage: www.beco.cc/compiler/brainforce
License: CC-3.0 http://creativecommons.org/licenses/by-nc-sa/3.0/

Usage:
./brainforce input_file [-o output_file] [options]

input_file : a input file with source code in BrainForce language (.bf)
output_file : a generated C source code from the input file (.c)

Options:
-zn :
n=0 default behavior
n=1 set zero = '0' for pretty print of chars
n=2 set cells to read/write integers
-d : print the syntax tree of the input_file
-v : verbosity mode. Can pile up till level 10
-q : quiety mode
-E : stop after preprocessor and write output_file.i (not implemented)
-S : stop after assembler and write output_file.s (not implemented)
-C : stop after C generator and write output_file.c (default)
-o file : output file name (default .c)
-h : print this help

BrainForce Source File:
Command Meaning
> increment the data pointer (to point to the next cell to the right).
< decrement the data pointer (to point to the next cell to the left).
+ increment (increase by one) the byte at the data pointer.
- decrement (decrease by one) the byte at the data pointer.
. output a character, the ASCII value of which being the byte at the data pointer.
, accept one byte of input, storing its value in the byte at the data pointer.
[ if the byte at the data pointer is zero, then jump forward to the command after the matching ] command.
] if the byte at the data pointer is nonzero, then jump back to the command after the matching [ command.
# debug: print the first 10 cells
*/


A linha de comando:

O compilador chamado de
 brainforce
é chamado na linha de comando com a syntaxe e opção dos seguintes argumentos:

uso:

$./brainforce arquivoentrada.bf [-o arquivosaida.c] [opções]


As opções disponíveis são:

-zn :
n=0 comportamento padrão compatível com a definição da linguagem original
n=1 faz o zero = '0', valor ASCII 48, para imprimir caracteres de modo mais legível
n=2 usa inteiros nos comandos de ler ',' e imprimir '.'
-d : imprime a árvore de sintaxe gerada pelo compilador
-v : aumenta a saída de mensagens de compilação. Pode ser usada de 1 a 10 vezes
-q : ativa o modo silencioso, diminuindo as mensagens de compilação
-E : roda apenas o preprocessador com arquivo de saída arquivo.i (não implementado)
-S : roda apenas o assembler, dando saída ao código assembly arquivo.s (não implementado)
-C : traduz o código do Brain Force para linguagem C na saída arquivo.c (é o modo padrão)
-o nome_arquivo : nome do arquivo de saída (sem definir, imprime na saída padrão,
-h : imprime esta ajuda


Como se pode ver, são muitas opções. Mas o mais impressionante é que esta pequena linguagem é Turing-Completa. Ou seja, é capaz de fazer qualquer coisa que as atuais linguagens mais poderosas do existentes, basta você ter muito tempo, e não ter vida social nenhuma.

Sunday, April 3, 2011

Mini Cliente em C

Este é um exemplo de código para um cliente mínimo, que envia um byte (letra C) para o servidor, e lê outro byte do servidor, pela internet. As tarefas para se conseguir isso são realizadas na ordem:

  1. Creating socket... done!
  2. Connecting... done!
  3. Writing "C"... done!
  4. Reading... "S" done!
Abaixo o código:

/*
Program: mincli.c
Author: Dr Beco
Date: 2001-04-03
Objective:
show a minimum client program that can
connect to a network, write a byte, read a byte, disconnect
*/

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>

#define BUFFER 2

int main(void)
{
printf("Configuring environment... ");

char data[BUFFER];
const char *host_server="localhost";
struct sockaddr_in dir;
struct hostent *host;
int aux, id, p=3333; //port

dir.sin_port = p;
dir.sin_family = AF_INET;
host = gethostbyname(host_server);
if(host == NULL)
return -1;
dir.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
printf("done!\n");

printf("Creating socket... ");
id = socket(AF_INET, SOCK_STREAM, 0);
if(id == -1)
return -1;
printf("done!\n");

printf("Connecting... ");
if(connect(id, (struct sockaddr *)&dir, sizeof(dir)) == -1)
return -1;
printf("done!\n");

printf("Writing \"C\"... ");
aux = send(id, "C", 1, MSG_NOSIGNAL);
if(aux < 0)
return -1;
printf("done!\n");

printf("Reading... ");
aux = read(id, data , 1);
if(aux!=1)
return -1;
printf("\"%c\"", data[0]);
printf(" done!\n");
return 0;
}

Mini Servidor em C

Este é um exemplo de código para um servidor mínimo, que lê um byte (letra) e envia outro byte (letra S) pela internet. As tarefas para se conseguir isso são realizadas na ordem:

  1. Configuring environment... done!
  2. Creating socket... done!
  3. Configuring socket... done!
  4. Binding... done!
  5. Listening... done!
  6. Accepting... done!
  7. Reading... "C"done!
  8. Writing "S"... done!

Abaixo o código:
/*
Program: minser.c
Author: Dr Beco
Date: 2001-04-03
Objective:
show a minimum server program that can
create a socket, accept a client, read a byte, write a byte, disconnect
*/

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/un.h>

#define BUFFER 2

int main(void)
{
printf("Configuring environment... ");

int p = 3333; // port
char data[BUFFER];
struct sockaddr_in dir;
struct sockaddr client;
socklen_t long_client;
int id, idReuse=1, son, aux;

memset(&dir,0,sizeof(dir));
dir.sin_port = p;
dir.sin_family = AF_INET;
dir.sin_addr.s_addr = INADDR_ANY;
printf("done!\n");

printf("Creating socket... ");
id = socket(AF_INET, SOCK_STREAM, 0);
if (id == -1)
return -1;
printf("done!\n");

printf("Configuring socket... ");
if(setsockopt(id,SOL_SOCKET,SO_REUSEADDR,&idReuse,sizeof(idReuse))==-1)
return -1;
printf("done!\n");

printf("Binding... ");
if(bind(id, (struct sockaddr *)&dir, sizeof(dir)) == -1)
{
close (id);
return -1;
}
printf("done!\n");

printf("Listening... ");
if (listen(id , 1) == -1)
{
close(id);
return -1;
}
printf("done!\n");

printf("Accepting... ");
long_client = sizeof (client);
son = accept(id, &client, &long_client);
if (son == -1)
return -1;
printf("done!\n");

printf("Reading... ");
aux = read(son, data , 1);
if(aux!=1)
return -1;
printf("\"%c\" ", data[0]);
printf("done!\n");

printf("Writing \"S\"... ");
aux = send(son, "S", 1, MSG_NOSIGNAL);
if(aux < 0)
return -1;
printf("done!\n");

return 0;
}

Wednesday, March 30, 2011

Acabo de instalar o Firefox 4 no UBUNTU 10.04


Muito bom! Muito mais rápido, e com visual mais clean. Para instalar você precisa seguir esses passos:
  1. Vá no menu Applications e clique em Ubuntu Software Center.
  2. Clique em Edit e em Software Sources.
  3. Clique na guia Other Software, e em Add.
  4. Em APT Line adicione a linha: ppa:mozillateam/firefox-stable
  5. Aguarde um pouco o update acontecer e pode fechar a janela.
  6. Vá em System, em Administration e chame o Update Manager.
  7. Feche o seu navegador firefox. Antes, leia o passo 8. :)
  8. Clique em Check e depois do gerenciador achar as atualizações, clique em Install Updates.


Prontinho! Pode reiniciar o firefox novo! O bom é que a partir de agora você terá cadastrado o site do firefox no seu source lists e terá sempre a última versão nos updates.

Na foto, além de conferir o visual do Firefox 4, a janela about com a versão, e o draft deste post, note um círculo verde no botão HTML ENCODE SELECTION. Este é o botão que é instalado pelo passo 3.2 do post Como postar código fonte no blog (26/mar/2011).

Referência
[1] Firefox 4 PPA

Contar palavras em uma frase

Um amigo meu na USP esta iniciando o curso de TI, e aprendendo a programar em C. Fez como desafio uma função Conta_Ocorrs() para contar o número de ocorrência de uma palavra em uma dada frase. Aproveitei seu algoritmo para ensinar algumas práticas melhores, comentei seus erros, corrigi, e também sugeri uma nova função contaoc().

Na nova função, discuti se vale a pena incluir um break para sair da função, ou se é melhor deixar o laço acabar por exaustão.

Abaixo a solução:


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

#define MAX 80

//funcao Conta_Ocorrs antes do main
//evita ter que escrever o prototipo
//int Conta_Ocorrs(char *pal, char *fra); //<= repare o ponto-e-virgula no prototipo

int Conta_Ocorrs(char *pal, char *fra)
{
int k; //conta as buscas da palavra na frase
int r; //conta as ocorrencias de caracteres de palavra em frase
int o=0; //conta as ocorrencias aqui!
int n, m;

//n=sizeof(fra); Este operador da o tamanho do "tipo" de variavel (int eh 2 bytes, char eh 1 byte, etc).
//m=sizeof(pal); Nao da o tamanho da string. Para isso, use:
n=strlen(fra);
m=strlen(pal);
printf("Tamanhos: frase: %d, palavra: %d\n", n, m);

for (k=m;k<=n;k++)
{
r=1; //r eh zerado em cada pesquisa -- os indices comecam em zero
while (r<=m && pal[m-r]==fra[k-r]) //r<=m para dar zero
r++;
if (r>=m)
o++;
}
return o;
}

//a funcao acima conta comparando indices de tras para frente, o que afeta o desempenho
//o melhor eh comparar os indices na direcao da memoria, para deixar o compilador otimizar melhor o codigo
//descomente os printfs abaixo para ver os indices.
//testei com as frases
//teste 1: frase: "a casa bonita casa". palavra: "casa"
//teste 2: frase: "mamama". palavra: "mama"
//teste 3: frase: "a casa bonita cas". palavra: "casa"
int contaoc(char *pal, char *fra)
{

int p=0; //indice da palavra
int f=0; //indice da frase
int o=0; //ocorrencias
// int tfra, tpal; //use nomes melhores para lembrar do que se trata

// tfra=strlen(fra); //sera que vale a pena conferir?
// tpal=strlen(pal); //veja resposta abaixo

//aproveito que se sabe que ao final de uma string sempre tem o caracter nulo '/0'
while(fra[f+p]!='\0')
{
// printf("outside p:%d, f:%d, o:%d\n", p, f, o);
while(pal[p]!='\0' && fra[f+p]!='\0' && pal[p]==fra[f+p])
// {
// printf("inside p:%d, f:%d, o:%d\n", p, f, o);
p++;
// }
if(pal[p]=='\0') //o pal[p] foi ate o fim, entao encontrou ocorrencia, caso contrario, acabou a frase ou sao diferentes
o++;

//evita calcular o restinho da frase menor que a palavra
// if(f+tpal > tfra)
// {
// printf("strlen p:%d, f:%d, o:%d\n", p, f, o);
// break;
// }
//talvez nao valha a pena. Vejamos:
//A frase "a casa bonita casa" tem 18 letras. A palavra "casa" tem 4. Somente quando f=15, as ultimas 3 letras da frase
//teremos o break. Isso vai evitar 3 giradas do laco externo (e talvez do interno se a frase fosse "a casa bonita cas")
//estamos falando de evitar entao:
// 3 whiles externos e no pior caso, 3+2+1 whiles internos com seus respectivos p++, mais 3 if(pal[p]=='\0')
// mais 3 p=0 e f++
// TOTAL de 24 operacoes
// Incluindo o if(t+tpal>tfra) e seu break, eliminamos 24 operacoes, mas inserimos:
// 2 strlen() no inicio
// para casa laco externo antes dos 3 ultimos (ou seja, 15 lacos): um if(t+tpal..., e a adicao em si do t+tpal
// TOTAL de 30 operacoes!!!
// Caso geral: supoe-se que frases podem ser maiores, mas as palavras acabam por ter um tamanho limitado
// Portanto, em um caso geral, a frase maior e uma palavra de tamanho limitado
// no algoritmo com break: aumenta o total de operacoes do if do break, e nao diminui consideravelmente os lacos
// no algoritmo sem break: o restinho do laco continua sendo executado sem necessidade, mas o numero de operacoes permanece pequeno
// Conclusao: melhor deixar o laco sem teste de break

p=0;
f++;
}
// printf("return p:%d, f:%d, o:%d\n", p, f, o);
return o;
}


// Função principal

int main(void)
{
char palavra[MAX], frase[MAX]; //ponteiros nao sao vetores! Eh preciso alocar o espaco para guardar dados, e isso eh feito com vetor
// contadores mudaram para dentro da funcao int m,n; //Definicao dos contadores
// nao estava sendo utilizada int o; //Definicao do valor de retorno da funcao

//Entrada de dados (inverti a ordem para melhor clareza)
printf("Entre com a frase (max %d letras pois 1 fica reservado para o caracter nulo): ", MAX-1);
//scanf("%s",frase); //nao se usa operador endereco & em ponteiros ou vetores
fgets(frase, MAX-1, stdin); //scanf para de ler ao ver espaco. use fgets(). fgets inclui o ENTER ao final. Elimine-o se nao quiser
frase[strlen(frase)-1]='\0'; //eliminando o ENTER final. Veja explicacao do strlen na funcao acima
printf("Entre com a palavra (max %d letras pois 1 fica reservado para o caracter nulo): ", MAX-1);
scanf("%s",palavra); //nao se usa operador endereco & em ponteiros ou vetores

//Inicializacao dos contadores pode ser feita na funcao, para diminuir numero de parametros
//m=sizeof(palavra);
//n=sizeof(frase);

//Saida de dados
printf("A palavra %s ocorre %d vez(es) na frase\n",palavra, Conta_Ocorrs(palavra, frase));
printf("Funcao contaoc(pal,fra): ocorrencias %d\n", contaoc(palavra, frase));

//Fim
//Nunca use isto. Seu algoritmo nao depende de sistema operacional. system("pause");
//Se precisa dar um tempo antes de retornar, use:
//getchar();
//mas o melhor eh aprender a executar o programa na linha de comando do prompt (shell)
}

Saturday, March 26, 2011

Como postar código fonte no blog

Não sem dificuldade, pesquisei e instalei o necessário para poder colocar no blog código fonte. Para que isso seja possível, com os simples 4 passos:

1- Colar o código no post, na janela de edit HTML
2- Selecioná-lo
3- Transformá-lo em HTML clicando no botão HTML ENCODE SELECTION
4- Colocar o código entre as tags <pre class="prettyprint"> e </pre>

É preciso antes configurar algumas coisas:

O item 3- O botão do item 3 não vem instalado por default. Para conseguí-lo é preciso:
3.1- instalar o add-on do firefox chamado greasemonkey, disponível na página GreaseMonkey Add-on
3.2- instalar o script que o greasemonkey usa para incluir o botão HTML ENCODE SELECTION. Para isso, após instalado, clique em: Script HTML ENCODE SELECTION
O greasemonkey deve aparecer na tela confirmando se quer instalar o script.

O item 4- As tags <pre class="prettyprint"> e </pre> não estão prontas para serem usadas. Para instalá-las é preciso:
4.1- Vá para as configurações do seu blog e edite o HTML Template
4.2- Faça um backup do código HTML antes de alterá-lo
4.3- Adicione na tag "head" o código (este é para o google-prettify, mas podem ser usados outros como o SyntaxHighlighter).

<link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" rel="stylesheet" type="text/css"/>
<script src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js" type="text/javascript"/>


4.4- Crie a tag "pre" adicionando o código:

pre {
margin: 5px 20px;
border: 1px dashed #666;
padding: 5px;
background: #f8f8f8;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}


4.5- Adicione dentro da tag "body" o código:

- <body>
+ <body onload='prettyPrint()'>


4.6- Salve o novo template. Agora sim você pode inserir código fonte de modo fácil, como descrito acima.

Referências

References:
1. Vivian's Tech Blog
2. How to publish source code in Blogger.com
3. Posting source code on Blogger
4. HTML TO ENCODE SELECTION

Finalmente em casa

Muito bom! O blog foi transportado para o domínio beco.cc
(Marco: 2011-03-26)