PDA

View Full Version : [Varie] Bitwise operations


The_ouroboros
22-02-2013, 14:41
Sono a casa in malattia e la mente divaga...
Il pensiero mi è ricaduto a qualche giorno fa quando debuggavo un programma e mi è sorta una domanda..
Chi usa ancora, con le moderne pipeline dei processori, le Bitwise operations?

Nel senso, a parte gli ambiente embedded, ovvio :D

Invero mi sa che, sempre con i moderni processori, anche usare lo xorg per swappare registri senza appoggio non sia tanto conveniente..

Vincenzo1968
22-02-2013, 15:11
Invero mi sa che, sempre con i moderni processori, anche usare lo xorg per swappare registri senza appoggio non sia tanto conveniente..

Credo anch'io ma ci sono casi in cui è ancora conveniente utilizzarli(i singoli bit, dico).

Per esempio, se dobbiamo memorizzare su file una serie di valori booleani e vogliamo risparmiare spazio su disco, con un solo byte(anziché 8), riusciamo a memorizzare 8 valori.

The_ouroboros
22-02-2013, 15:14
a mio parere anche come "simple configuration".
Ti fai una bella flaglist dove attivi/disattivi bit a cui dai un significato preciso.
Però, tanto per dire...

#include <stdio.h>

int foo(){
return 0;
}
In C, con il Gcc, se non metti ottimizzazioni e fino a -O1 lo traduce in

foo():
mov eax, 0
ret

Mentr con -O2

foo():
xor eax, eax
ret

Vincenzo1968
22-02-2013, 15:18
Eh ma io compilo sempre con -O3. Non ci dormirei la notte pensando che la mia applicazione non è ottimizzata fino al midollo. :D

The_ouroboros
22-02-2013, 15:20
mmm secondo me -O3 è anche troppo..

cdimauro
22-02-2013, 16:34
Sono a casa in malattia e la mente divaga...
Il pensiero mi è ricaduto a qualche giorno fa quando debuggavo un programma e mi è sorta una domanda..
Chi usa ancora, con le moderne pipeline dei processori, le Bitwise operations?

Nel senso, a parte gli ambiente embedded, ovvio :D

Invero mi sa che, sempre con i moderni processori, anche usare lo xorg per swappare registri senza appoggio non sia tanto conveniente..
Io le uso ancora anche in Python, se vedo che mi possono essere utili.

Non è soltanto una questione di ottimizzazione, ma di corretto utilizzo di uno strumento che hai a disposizione, e che da programmatore fa parte della tua "cassetta degli attrezzi".

The_ouroboros
22-02-2013, 16:42
Non è soltanto una questione di ottimizzazione, ma di corretto utilizzo di uno strumento che hai a disposizione, e che da programmatore fa parte della tua "cassetta degli attrezzi".

Su questo mi trovi completamente d'accordo :D

The_ouroboros
22-02-2013, 17:03
Curioso è che questi argomenti a volte sono considerati "marginali" :D
Quando invece tornano utilissimi in molti campi..

Inviato dal mio Sony Xperia P

Vincenzo1968
22-02-2013, 17:07
Anche nella api di Windows(che ovviamente è in C) gli operatori bitwise sono usati per risparmiare spazio(ma in memoria, non su disco):

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633584%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633584%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543%28v=vs.85%29.aspx

Vedi? Sono usati per memorizzare l'ID della finestra, gli stili, gli stili estesi etc, e consentono di risparmiare un bel po' di memoria per ogni finestra aperta.

The_ouroboros
22-02-2013, 17:11
Ottimo esempio.. Non ne ero a conoscenza :)

Inviato dal mio Sony Xperia P

cdimauro
22-02-2013, 17:16
Gli ID (handle) delle finestre non sono bitfield/mask, ma interi.

Il resto è corretto.

The_ouroboros
22-02-2013, 17:18
Il c/c++ ha un accrocchio apposta per i bitfield mi pare di ricordare..

http://www.science.unitn.it/~fiorella/guidac/guidac072.html



Inviato dal mio Sony Xperia P

cdimauro
22-02-2013, 17:34
Sì, è uno strumento abbastanza grezzo introdotto col C.

Ma linguaggi come Pascal e Modula-2 ne mettono a disposizione una versione molto più elegante, di alto livello, e semplice da usare.

The_ouroboros
22-02-2013, 17:43
Mi sembra soffra pure di endiannes..

The_ouroboros
22-02-2013, 17:44
Ma linguaggi come Pascal e Modula-2 ne mettono a disposizione una versione molto più elegante, di alto livello, e semplice da usare.
Really?

cdimauro
22-02-2013, 18:04
Mi sembra soffra pure di endiannes..
Togli pure il mi sembra: è una caratteristica non portabile del C, proprio per l'endianess. :D
Really?
Sì. Il Pascal ha il concetto di Set, mentre in Modula-2 c'è proprio il BitMask (non ricordo se il tipo si chiama così).

The_ouroboros
22-02-2013, 18:09
Forte!
A python come stiamo?

Vincenzo1968
22-02-2013, 18:26
Qui c'è un bell'esempio per cambiare lo stile di una finestra al volo:

http://bcbjournal.org/articles/vol4/0004/Changing_window_styles_on_the_fly.htm?PHPSESSID=5a23d7eaa24b1c589983aab875aaeeb6


Changing styles at run time

Changing styles at runtime requires just a few lines of code. First you get the current window style. Next you add or remove style bits as needed. Finally, you reset the window style to the new style bits. Here’s how the code looks:


long style = GetWindowLong(
ProgressBar1->Handle, GWL_EXSTYLE);
style &= ~WS_EX_STATICEDGE;
SetWindowLong(ProgressBar1->Handle,
GWL_EXSTYLE, style);


This code removes the WS_EX_STATICEDGE style from the progress bar. To add this style back you would use code like this:


long style = GetWindowLong(
ProgressBar1->Handle, GWL_EXSTYLE);
style |= WS_EX_STATICEDGE;
SetWindowLong(ProgressBar1->Handle,
GWL_EXSTYLE, style);



Typically you will place this code in your form’s constructor or on OnCreate event handler.

Ma mi pare di ricordare che si debba chiamare anche l'api SetWindowsPos altrimenti l'aspetto della finestra non cambia nonostante i cambiamenti effettuati con SetWindowLong.

In XWindows su Linux dovrebbe esserci qualche meccanismo simile. Presto lo saprò; datemi il tempo di studiarmi l'api e ve lo dirò(10-20-30 anni). Presto insomma. ;)

EDIT: Ah, si esatto, ricordavo bene. sono andato a rispolverare il Petzold:


SetWindowPos(WindowHandle,
HWND_TOP,
0,
0,
0, //New Width
0, //New Height,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

cdimauro
22-02-2013, 18:30
Forte!
A python come stiamo?
Non c'è nessun supporto ufficiale ai bitfield/mask perché, essendo disponibile il tipo Set (e FronzenSet), si possono gestisce in scioltezza ed estrema semplicità gli insiemi come matematica insegna (con tutte le operazioni "classiche" definite):
a = {0, 1, 5, 7}
b = {2, 5, 6, 7}
c = a | b
print c # Stampa: set([0, 1, 2, 5, 6, 7])

In alternativa, per chi vuole o lo ritiene opportuno, si definiscono le classiche costanti e si usano gli interi.

Vincenzo1968
22-02-2013, 18:39
Sì, è uno strumento abbastanza grezzo introdotto col C.

Ma linguaggi come Pascal e Modula-2 ne mettono a disposizione una versione molto più elegante, di alto livello, e semplice da usare.

Ah ok.

Mi disiscrivo dai, che mi si rompono i cabasisi a leggere di cdimauro che parla male del C.

Comunque non è che ci vuole l'arte di Pinna per leggere l'endianess del sistema e agire di conseguenza:


char isBigEndian()
{
short i = 0xABCD;
unsigned char *buff;

buff = (unsigned char*)&i;

if( buff[0] == 0xAB )
return 1;

return 0;
}


Sarà un po' macchinoso ma è estremamente efficiente. Tutto il contrario rispetto a python che è estremamente inefficiente: lento, lento, lento! Insopportabilmente lento. Lento ma così lento che più lento non si può.

Disiscritto dai. ;)

cdimauro
22-02-2013, 19:06
Ah ok.

Mi disiscrivo dai, che mi si rompono i cabasisi a leggere di cdimauro che parla male del C.
Sei ossessionato dal C. Ogni critica per te è fumo negli occhi.

Non posso farci nulla se il Pascal, che peraltro è nato prima del C, offre un meccanismo più elegante per lo stesso concetto. Prenditela con Ritchie e Kernighan. :Prrr:
Comunque non è che ci vuole l'arte di Pinna per leggere l'endianess del sistema e agire di conseguenza:


char isBigEndian()
{
short i = 0xABCD;
unsigned char *buff;

buff = (unsigned char*)&i;

if( buff[0] == 0xAB )
return 1;

return 0;
}


Sarà un po' macchinoso ma è estremamente efficiente.
A parte il fatto che stai giocando coi puntatori in maniera sporca, in questo modo puoi soltanto capire qual è l'endianess, ma non risolvi il problema.

Dovresti definire due struct per i bitfield, e usare l'una o l'altra a seconda se il tuo sistema è big o little endian. Una cosa un po' pallosa e non di immediato utilizzo, visto che devi farlo a runtime (col tuo esempio). :read:
Tutto il contrario rispetto a python che è estremamente inefficiente: lento, lento, lento! Insopportabilmente lento. Lento ma così lento che più lento non si può.
Chi si accontenta gode. :cool:

The_ouroboros
22-02-2013, 19:16
Non c'è nessun supporto ufficiale ai bitfield/mask perché, essendo disponibile il tipo Set (e FronzenSet), si possono gestisce in scioltezza ed estrema semplicità gli insiemi come matematica insegna (con tutte le operazioni "classiche" definite):
a = {0, 1, 5, 7}
b = {2, 5, 6, 7}
c = a | b
print c # Stampa: set([0, 1, 2, 5, 6, 7])

In alternativa, per chi vuole o lo ritiene opportuno, si definiscono le classiche costanti e si usano gli interi.

Ho visto anche che prefissando 0b ad un numero posso usarlo come binario e "giocare" con &,^,<<,>>,~ e |…

cdimauro
22-02-2013, 19:19
Sì, esatto, in questo modo puoi introdurre numeri interi in notazione binaria (poi c'è anche l'ottale e l'esadecimale), con la quale viene comodo definire sequenze di bit.

The_ouroboros
22-02-2013, 19:23
Sempre più interessante sto serpentello...
Cmq è una valigia utile quella del "lavoro di bit" ;)

The_ouroboros
22-02-2013, 20:17
Bitwise operators are operators that work on multi-bit values, but conceptually one bit at a time.

AND is 1 only if both of its inputs are 1, otherwise it's 0.
OR is 1 if one or both of its inputs are 1, otherwise it's 0.
XOR is 1 only if exactly one of its inputs are 1, otherwise it's 0.
NOT is 1 only if its input is 0, otherwise it's 0.

These can often be best shown as truth tables. Input possibilities are on the top and left, the resultant bit is one of the four (two in the case of NOT since it only has one input) values shown at the intersection of the inputs.

AND | 0 1 OR | 0 1 XOR | 0 1
----+----- ---+---- ----+----
0 | 0 0 0 | 0 1 0 | 0 1
1 | 0 1 1 | 1 1 1 | 1 0

One example is if you only want the lower 4 bits of an integer, you AND it with 15 (binary 1111) so:

201: 1100 1001
AND 15: 0000 1111
------------------
IS 9 0000 1001

The zero bits in 15(0b1111) in that case effectively act as a filter, forcing the bits in the result to be zero as well.

Another example is if you have two 4-bit values that you want to pack into an 8-bit one, you can use all three of your operators (left-shift, and and or):

packed_val = ((val1 & 15) << 4) | (val2 & 15)

1. The & 15 operation will make sure that both values only have the lower 4 bits.
2. The << 4 is a 4-bit shift left to move val1 into the top 4 bits of an 8-bit value.
3. The | simply combines these two together.

If val1 is 7 and val2 is 4:

val1 val2
==== ====
& 15 (and) xxxx-0111 xxxx-0100 & 15
<< 4 (left) 0111-0000 |
| |
+-------+-------+
|
| (or) 0111-0100


fonte: http://stackoverflow.com/questions/1746613/bitwise-operation-and-usage

sottovento
23-02-2013, 07:40
Sono a casa in malattia e la mente divaga...
Il pensiero mi è ricaduto a qualche giorno fa quando debuggavo un programma e mi è sorta una domanda..
Chi usa ancora, con le moderne pipeline dei processori, le Bitwise operations?

Nel senso, a parte gli ambiente embedded, ovvio :D

Chiunque scrivi un driver o, in maniera piu' generale, abbia bisogno di accedere da un dispositivo hardware. Chi gioca con l'hardware preferisce ragionare in termini di segnali (i.e. bit) e non te li mette in byte diversi perche' costerebbe molto di piu'. Questo vale per chiunque, non solo per gli ambienti embedded.

sottovento
23-02-2013, 07:46
Togli pure il mi sembra: è una caratteristica non portabile del C, proprio per l'endianess. :D


Dipende da cosa intendi. Ci sono degli standard (lo so, mettere nella stessa frase "C" e "Standard" fa ridere. Potrei addirittura candidarmi alle elezioni), per cui i bit field vendono definiti a partire da LSB. Pertanto


struct MyStruct
{
unsigned int b0 : 1;
unsigned int b1 : 1;
unsigned int b2 : 1;
unsigned int b3 : 1;
unsigned int b4 : 1;
unsigned int b5 : 1;
unsigned int b6 : 1;
unsigned int b7 : 1;
unsigned int b8 : 1;
unsigned int b9 : 1;
unsigned int b10 : 1;
unsigned int b11 : 1;
unsigned int b12 : 1;
unsigned int b13 : 1;
unsigned int b14 : 1;
unsigned int b16 : 1;
unsigned int b17 : 1;
unsigned int b18 : 1;
unsigned int b19 : 1;
unsigned int b20 : 1;
unsigned int b21 : 1;
unsigned int b22 : 1;
unsigned int b23 : 1;
unsigned int b24 : 1;
unsigned int b25 : 1;
unsigned int b26 : 1;
unsigned int b27 : 1;
unsigned int b28 : 1;
unsigned int b29 : 1;
unsigned int b30 : 1;
unsigned int b31 : 1;
};

int main(int argc, char *argv[])
{
int val = 0x01;
MyStruct *p = (MyStruct *)&val;

printf ("b0: %d b31:%d\n", p->b0, p->b31);
}

generera' lo stesso output indipendentemente dall'endianness della macchina su cui gira.


Sì. Il Pascal ha il concetto di Set, mentre in Modula-2 c'è proprio il BitMask (non ricordo se il tipo si chiama così).

Sia Pascal sia Modula-2 introducono i concetti di Set. Ma sono concetti ad alto livello, la loro rappresentazione non e' specificata. Il C, invece, e' fatto per rompere le scatole e lo deve fare fino in fondo :D

Altra cosa: se parli di Modula-2 significa che hai anche tu passato la quarantina. Mamma mia, stiamo invecchiando ;)

sottovento
23-02-2013, 07:54
Ah ok.
Mi disiscrivo dai, che mi si rompono i cabasisi a leggere di cdimauro che parla male del C.

Sai che ci teniamo ai tuoi cabasisi! Su, dai, mettili nel cassetto, al sicuro :D


Comunque non è che ci vuole l'arte di Pinna per leggere l'endianess del sistema e agire di conseguenza:


char isBigEndian()
{
short i = 0xABCD;
unsigned char *buff;

buff = (unsigned char*)&i;

if( buff[0] == 0xAB )
return 1;

return 0;
}


Sarà un po' macchinoso ma è estremamente efficiente.

No, non e' macchinoso, e' la maniera corretta di procedere. Cmq, come scrivevo, non hai bisogno di conoscere l'endianness per definire la bitfield (e non potresti nemmeno). Al massimo sapere se sei su macchina big endian/little endian ti puo' servire se hai bisogno di accedere mediante mask a dei bit da words/double words.
Sempre che queste word arrivino da un sistema diverso (per esempio, stai leggendo lo stato di un dispositivo o decodificando dati via rete), altrimenti anche questo non ha senso

The_ouroboros
23-02-2013, 07:59
Chiunque scrivi un driver o, in maniera piu' generale, abbia bisogno di accedere da un dispositivo hardware. Chi gioca con l'hardware preferisce ragionare in termini di segnali (i.e. bit) e non te li mette in byte diversi perche' costerebbe molto di piu'. Questo vale per chiunque, non solo per gli ambienti embedded.

Interessante prospettiva.
Qualche info in più? :D

sottovento
23-02-2013, 08:33
Interessante prospettiva.
Qualche info in più? :D

Cioe'? Sui bitfield? O l'accesso all'hardware?

cdimauro
23-02-2013, 08:43
Dipende da cosa intendi. Ci sono degli standard (lo so, mettere nella stessa frase "C" e "Standard" fa ridere. Potrei addirittura candidarmi alle elezioni), per cui i bit field vendono definiti a partire da LSB.
In realtà lo standard ANSI e ISO lasciano indefinita l'implementazione dei campi di bit. Ecco perché parlavo di funzionalità non portabile del linguaggio.
Pertanto


struct MyStruct
{
unsigned int b0 : 1;
[...]
unsigned int b31 : 1;
};

int main(int argc, char *argv[])
{
int val = 0x01;
MyStruct *p = (MyStruct *)&val;

printf ("b0: %d b31:%d\n", p->b0, p->b31);
}

generera' lo stesso output indipendentemente dall'endianness della macchina su cui gira.
Se il compilatore alloca i bit sempre dall'LSB, come avevi supposto, dovrebbe dare un risultato diverso a seconda che la macchina sia little o big endian.

Se, invece, su macchina little endian parte dall'LSB, mentre per quelle big endian parte dall'MSB, allora il risultato sarà uguale.

Comunque rimane sempre da vedere come si comporta il compilatore (ci sarebbe da considerare anche il padding dei bit, che è anch'esso indefinito).

Altra cosa, se si definiscono meno bit rispetto alla dimensione della parola di macchina, come usualmente avviene (difficile che si allochino tutti i bit ogni volta), sorgono problemi.
Sia Pascal sia Modula-2 introducono i concetti di Set. Ma sono concetti ad alto livello, la loro rappresentazione non e' specificata. Il C, invece, e' fatto per rompere le scatole e lo deve fare fino in fondo :D
Alla fine dipende dall'implementazione, come per il C. Una volta che sai come il compilatore alloca i bit, puoi fare quello che vuoi, e... si faceva (almeno io col Turbo Pascal di Borland). :cool:
Altra cosa: se parli di Modula-2 significa che hai anche tu passato la quarantina. Mamma mia, stiamo invecchiando ;)
Già. La cifra delle unità è pari a 2 nel mio caso. :stordita:

The_ouroboros
23-02-2013, 08:44
Cioe'? Sui bitfield? O l'accesso all'hardware?

Sul "giocare" con i segnali :cool:

sottovento
23-02-2013, 09:09
Sul "giocare" con i segnali :cool:

Bella domanda, ma forse troppo generica oltre che OT.
Per limitare un pochino, potrei dire che l'accesso all'hardware ("giocare" con i segnali) puo' essere fatto in maniera diversa a seconda
- del processore;
- dello standard di bus a cui il tuo hardware e' collegato (o all'assenza di standard);
- della quantita' di dati che si vuole scambiare;
- del tipo dei dati che si vuole scambiare.

La prima divisione che si puo' pensare e' fra I/O "classico" e "memory mapped". Alcuni processori tuttavia non possono fare questa distinzione. Il primo esempio che mi viene in mente sono i processori Motorola 68x che non avevano l'I/O classico ma tutto mappato in memoria.
Questo significa che accedere al dispositivo "semplicemente" significa scrivere/leggere a determinati indirizzi.

Ma forse la tua domanda era piu' semplice. Se vuoi cominciare a "giocare" ed ottenere qualcosa di utile (per esempio, poter controllare le luci di casa con il computer, magari anche attraverso internet/mail/sms) potresti guardare i kit di Nuova Elettronica (si, esiste ancora!!!), che funzionano SEMPRE!
Te li devi montare, quindi c'e' anche quel divertimento. Ti serve un minimo di conoscenze di elettronica. Niente di trascendentale, ma quanto meno devi saper maneggiare un saldatore ;)

The_ouroboros
23-02-2013, 09:35
La prima divisione che si puo' pensare e' fra I/O "classico" e "memory mapped". Alcuni processori tuttavia non possono fare questa distinzione. Il primo esempio che mi viene in mente sono i processori Motorola 68x che non avevano l'I/O classico ma tutto mappato in memoria.
Questo significa che accedere al dispositivo "semplicemente" significa scrivere/leggere a determinati indirizzi.



Interessante, moolto interessante :eek:

Vincenzo1968
23-02-2013, 09:41
No, non e' macchinoso, e' la maniera corretta di procedere. Cmq, come scrivevo, non hai bisogno di conoscere l'endianness per definire la bitfield (e non potresti nemmeno). Al massimo sapere se sei su macchina big endian/little endian ti puo' servire se hai bisogno di accedere mediante mask a dei bit da words/double words.
Sempre che queste word arrivino da un sistema diverso (per esempio, stai leggendo lo stato di un dispositivo o decodificando dati via rete), altrimenti anche questo non ha senso

No no, quale maniera corretta di procedere? Vuoi babbiare? Sto giocando in maniera sporca coi puntatori!

Non mi riferivo comunque alla bitfield. Dicevo in generale, sugli operatori bitwise. Se un software ha bisogno di memorizzare i dati su file in formato big endian, e tu sei su un sistema little endian, quella funzione ti serve per sapere se prima di salvare i dati sul file devi convertire da little endian a big endian.
É quello che ho fatto per il punto 3 del contest 17. Il bytecode della jvm dev'essere, secondo quanto riportato dalle specifiche, in formato big endian.

Ma gioco in maniera sporca coi puntatori... Uh! i puntatori!

Disiscritto dai.

sottovento
23-02-2013, 09:47
In realtà lo standard ANSI e ISO lasciano indefinita l'implementazione dei campi di bit. Ecco perché parlavo di funzionalità non portabile del linguaggio.

Se la memoria non mi inganna, partire da lsb e' standard. Per questo che il codice sopra deve (dovrebbe?) dare gli stessi risultati indipendentemente dall'endianness.



Se il compilatore alloca i bit sempre dall'LSB, come avevi supposto, dovrebbe dare un risultato diverso a seconda che la macchina sia little o big endian.

Eh no! Cmq l'endianness del bit field e' lo stesso dell'intero da cui ho prelevato l'indirizzo.

Ad ogni modo, siamo perfettamente d'accordo che affidare il funzionamento di un programma a questi dettagli e' da pazzi. Cosi' come siamo d'accordo che il C/C++ sia un linguaggio il cui utilizzo debba essere limitato ai casi strettamente necessari, if any.



Già. La cifra delle unità è pari a 2 nel mio caso. :stordita:
Nel mio, 3. Dai, non siamo vecchi: siamo interessanti :D

Vincenzo1968
23-02-2013, 09:57
Dalla mia soluzione al contest 17:

endianess.h

#ifndef ENDIANESS_H
#define ENDIANESS_H

#define BYTE unsigned char

#define S1 signed char
#define S2 signed short
#define S4 signed long
#define S8 signed __int64
#define U1 unsigned char
#define U2 unsigned short
#define U4 unsigned long
#define U8 unsigned __int64

#define F4 float
#define F8 double


#define FORMAT_WORD(arr,start){ fb[0]=arr[start+1];\
fb[1]=arr[start];\
arr[start]=fb[0];\
arr[start+1]=fb[1]; }

#define FORMAT_DWORD(arr,start){ fb[0]=arr[start+3];\
fb[1]=arr[start+2];\
fb[2]=arr[start+1];\
fb[3]=arr[start];\
arr[start]=fb[0];\
arr[start+1]=fb[1];\
arr[start+2]=fb[2];\
arr[start+3]=fb[3]; }

#define FORMAT_QWORD(arr,start){ fb[0]=arr[start+7];\
fb[1]=arr[start+6];\
fb[2]=arr[start+5];\
fb[3]=arr[start+4];\
fb[4]=arr[start+3];\
fb[5]=arr[start+2];\
fb[6]=arr[start+1];\
fb[7]=arr[start];\
arr[start]=fb[0];\
arr[start+1]=fb[1];\
arr[start+2]=fb[2];\
arr[start+3]=fb[3];\
arr[start+4]=fb[4];\
arr[start+5]=fb[5];\
arr[start+6]=fb[6];\
arr[start+7]=fb[7]; }


char isBigEndian();

#endif /* ENDIANESS_H */


endianess.c

#include "endianess.h"

/*
ritorna 1 se la macchina è big-endian, 0 se little-endian
*/
char isBigEndian()
{
short i = 0xABCD;
unsigned char *buff;

buff = (unsigned char*)&i;

if( buff[0] == 0xAB )
return 1;

return 0;
}


jvm.h

#ifndef JVM_H
#define JVM_H

#define CONSTANT_Class 7
#define CONSTANT_Fieldref 9
#define CONSTANT_Methodref 10
#define CONSTANT_InterfaceMethodref 11
#define CONSTANT_String 8
#define CONSTANT_Integer 3
#define CONSTANT_Float 4
#define CONSTANT_Long 5
#define CONSTANT_Double 6
#define CONSTANT_NameAndType 12
#define CONSTANT_Utf8 1

#define ACC_PUBLIC 0x0001
#define ACC_PRIVATE 0x0002
#define ACC_PROTECTED 0x0004
#define ACC_STATIC 0x0008
#define ACC_FINAL 0x0010
#define ACC_SYNCHRONIZED 0x0020
#define ACC_SUPER 0x0020
#define ACC_VOLATILE 0x0040
#define ACC_TRANSIENT 0x0080
#define ACC_NATIVE 0x0100
#define ACC_INTERFACE 0x0200
#define ACC_ABSTRACT 0x0400
#define ACC_STRICT 0x0800


#define jvm_nop 0
#define jvm_aconst_null 1
#define jvm_iconst_m1 2
#define jvm_iconst_0 3
#define jvm_iconst_1 4
#define jvm_iconst_2 5
#define jvm_iconst_3 6
#define jvm_iconst_4 7
#define jvm_iconst_5 8
#define jvm_lconst_0 9
#define jvm_lconst_1 10
#define jvm_fconst_0 11
#define jvm_fconst_1 12
#define jvm_fconst_2 13
#define jvm_dconst_0 14
#define jvm_dconst_1 15
#define jvm_bipush 16
#define jvm_sipush 17
#define jvm_ldc 18
#define jvm_ldc_w 19
#define jvm_ldc2_w 20
#define jvm_iload 21
#define jvm_lload 22
#define jvm_fload 23
#define jvm_dload 24
#define jvm_aload 25
#define jvm_iload_0 26
#define jvm_iload_1 27
#define jvm_iload_2 28
#define jvm_iload_3 29
#define jvm_lload_0 30
#define jvm_lload_1 31
#define jvm_lload_2 32
#define jvm_lload_3 33
#define jvm_fload_0 34
#define jvm_fload_1 35
#define jvm_fload_2 36
#define jvm_fload_3 37
#define jvm_dload_0 38
#define jvm_dload_1 39
#define jvm_dload_2 40
#define jvm_dload_3 41
#define jvm_aload_0 42
#define jvm_aload_1 43
#define jvm_aload_2 44
#define jvm_aload_3 45
#define jvm_iaload 46
#define jvm_laload 47
#define jvm_faload 48
#define jvm_daload 49
#define jvm_aaload 50
#define jvm_baload 51
#define jvm_caload 52
#define jvm_saload 53
#define jvm_istore 54
#define jvm_lstore 55
#define jvm_fstore 56
#define jvm_dstore 57
#define jvm_astore 58
#define jvm_istore_0 59
#define jvm_istore_1 60
#define jvm_istore_2 61
#define jvm_istore_3 62
#define jvm_lstore_0 63
#define jvm_lstore_1 64
#define jvm_lstore_2 65
#define jvm_lstore_3 66
#define jvm_fstore_0 67
#define jvm_fstore_1 68
#define jvm_fstore_2 69
#define jvm_fstore_3 70
#define jvm_dstore_0 71
#define jvm_dstore_1 72
#define jvm_dstore_2 73
#define jvm_dstore_3 74
#define jvm_astore_0 75
#define jvm_astore_1 76
#define jvm_astore_2 77
#define jvm_astore_3 78
#define jvm_iastore 79
#define jvm_lastore 80
#define jvm_fastore 81
#define jvm_dastore 82
#define jvm_aastore 83
#define jvm_bastore 84
#define jvm_castore 85
#define jvm_sastore 86
#define jvm_pop 87
#define jvm_pop2 88
#define jvm_dup 89
#define jvm_dup_x1 90
#define jvm_dup_x2 91
#define jvm_dup2 92
#define jvm_dup2_x1 93
#define jvm_dup2_x2 94
#define jvm_swap 95
#define jvm_iadd 96
#define jvm_ladd 97
#define jvm_fadd 98
#define jvm_dadd 99
#define jvm_isub 100
#define jvm_lsub 101
#define jvm_fsub 102
#define jvm_dsub 103
#define jvm_imul 104
#define jvm_lmul 105
#define jvm_fmul 106
#define jvm_dmul 107
#define jvm_idiv 108
#define jvm_ldiv 109
#define jvm_fdiv 110
#define jvm_ddiv 111
#define jvm_irem 112
#define jvm_lrem 113
#define jvm_frem 114
#define jvm_drem 115
#define jvm_ineg 116
#define jvm_lneg 117
#define jvm_fneg 118
#define jvm_dneg 119
#define jvm_ishl 120
#define jvm_lshl 121
#define jvm_ishr 122
#define jvm_lshr 123
#define jvm_iushr 124
#define jvm_lushr 125
#define jvm_iand 126
#define jvm_land 127
#define jvm_ior 128
#define jvm_lor 129
#define jvm_ixor 130
#define jvm_lxor 131
#define jvm_iinc 132
#define jvm_i2l 133
#define jvm_i2f 134
#define jvm_i2d 135
#define jvm_l2i 136
#define jvm_l2f 137
#define jvm_l2d 138
#define jvm_f2i 139
#define jvm_f2l 140
#define jvm_f2d 141
#define jvm_d2i 142
#define jvm_d2l 143
#define jvm_d2f 144
#define jvm_i2b 145
#define jvm_i2c 146
#define jvm_i2s 147
#define jvm_lcmp 148
#define jvm_fcmpl 149
#define jvm_fcmpg 150
#define jvm_dcmpl 151
#define jvm_dcmpg 152
#define jvm_ifeq 153
#define jvm_ifne 154
#define jvm_iflt 155
#define jvm_ifge 156
#define jvm_ifgt 157
#define jvm_ifle 158
#define jvm_if_icmpeq 159
#define jvm_if_icmpne 160
#define jvm_if_icmplt 161
#define jvm_if_icmpge 162
#define jvm_if_icmpgt 163
#define jvm_if_icmple 164
#define jvm_if_acmpeq 165
#define jvm_if_acmpne 166
#define jvm_goto 167
#define jvm_jsr 168
#define jvm_ret 169
#define jvm_tableswitch 170
#define jvm_lookupswitch 171
#define jvm_ireturn 172
#define jvm_lreturn 173
#define jvm_freturn 174
#define jvm_dreturn 175
#define jvm_areturn 176
#define jvm_return 177
#define jvm_getstatic 178
#define jvm_putstatic 179
#define jvm_getfield 180
#define jvm_putfield 181
#define jvm_invokevirtual 182
#define jvm_invokespecial 183
#define jvm_invokestatic 184
#define jvm_invokeinterface 185
#define jvm_xxxunusedxxx 186
#define jvm_new 187
#define jvm_newarray 188
#define jvm_anewarray 189
#define jvm_arraylength 190
#define jvm_athrow 191
#define jvm_checkcast 192
#define jvm_instanceof 193
#define jvm_monitorenter 194
#define jvm_monitorexit 195
#define jvm_wide 196
#define jvm_multianewarray 197
#define jvm_ifnull 198
#define jvm_ifnonnull 199
#define jvm_goto_w 200
#define jvm_jsr_w 201
#define jvm_breakpoint 202
#define jvm_impdep1 254
#define jvm_impdep2 255


/*
char *I_Set[256] =
{
"nop",
"aconst_null",
"iconst_m1",
"iconst_0",
"iconst_1",
"iconst_2",
"iconst_3",
"iconst_4",
"iconst_5",
"lconst_0",
"lconst_1",
"fconst_0",
"fconst_1",
"fconst_2",
"dconst_0",
"dconst_1",
"bipush",
"sipush",
"ldc",
"ldc_w",
"ldc2_w",
"iload",
"lload",
"fload",
"dload",
"aload",
"iload_0",
"iload_1",
"iload_2",
"iload_3",
"lload_0",
"lload_1",
"lload_2",
"lload_3",
"fload_0",
"fload_1",
"fload_2",
"fload_3",
"dload_0",
"dload_1",
"dload_2",
"dload_3",
"aload_0",
"aload_1",
"aload_2",
"aload_3",
"iaload",
"laload",
"faload",
"daload",
"aaload",
"baload",
"caload",
"saload",
"istore",
"lstore",
"fstore",
"dstore",
"astore",
"istore_0",
"istore_1",
"istore_2",
"istore_3",
"lstore_0",
"lstore_1",
"lstore_2",
"lstore_3",
"fstore_0",
"fstore_1",
"fstore_2",
"fstore_3",
"dstore_0",
"dstore_1",
"dstore_2",
"dstore_3",
"astore_0",
"astore_1",
"astore_2",
"astore_3",
"iastore",
"lastore",
"fastore",
"dastore",
"aastore",
"bastore",
"castore",
"sastore",
"pop",
"pop2",
"dup",
"dup_x1",
"dup_x2",
"dup2",
"dup2_x1",
"dup2_x2",
"swap",
"iadd",
"ladd",
"fadd",
"dadd",
"isub",
"lsub",
"fsub",
"dsub",
"imul",
"lmul",
"fmul",
"dmul",
"idiv",
"ldiv",
"fdiv",
"ddiv",
"irem",
"lrem",
"frem",
"drem",
"ineg",
"lneg",
"fneg",
"dneg",
"ishl",
"lshl",
"ishr",
"lshr",
"iushr",
"lushr",
"iand",
"land",
"ior",
"lor",
"ixor",
"lxor",
"iinc",
"i2l",
"i2f",
"i2d",
"l2i",
"l2f",
"l2d",
"f2i",
"f2l",
"f2d",
"d2i",
"d2l",
"d2f",
"i2b",
"i2c",
"i2s",
"lcmp",
"fcmpl",
"fcmpg",
"dcmpl",
"dcmpg",
"ifeq",
"ifne",
"iflt",
"ifge",
"ifgt",
"ifle",
"if_icmpeq",
"if_icmpne",
"if_icmplt",
"if_icmpge",
"if_icmpgt",
"if_icmple",
"if_acmpeq",
"if_acmpne",
"goto",
"jsr",
"ret",
"tableswitch",
"lookupswitch",
"ireturn",
"lreturn",
"freturn",
"dreturn",
"areturn",
"return",
"getstatic",
"putstatic",
"getfield",
"putfield",
"invokevirtual",
"invokespecial",
"invokestatic",
"invokeinterface",
"xxxunusedxxx",
"new",
"newarray",
"anewarray",
"arraylength",
"athrow",
"checkcast",
"instanceof",
"monitorenter",
"monitorexit",
"wide",
"multianewarray",
"ifnull",
"ifnonnull",
"goto_w",
"jsr_w",
"breakpoint",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "",
"impdep1",
"impdep2"
};
*/

#include "symtab.h"
#include "ast.h"

#define JVM_HT_SIZE 4096

typedef struct tag_jvmHashTable
{
char *Key;
unsigned short c; /*indice constant pool table*/
struct tag_jvmHashTable *next;
} jvmHashTable;

jvmHashTable* jvmhtNewNode(char *Key, unsigned short c);
int jvmhtFind(jvmHashTable **pHashTable, char *Key, unsigned short *c);
void jvmhtInsert(jvmHashTable **pHashTable, char *Key, unsigned short c);
void jvmhtFree(jvmHashTable* first);

void jvmSetNumberLocals(int n);

void jvmWriteHeader(FILE *fp);
int jvmMakeConstantPool(char *szSourceFile, char *szClassName);
int jvmAddArrayClass(int type, int sizes, int index);
int jvmAddStringConstant(char *sz, int index);
int jvmAddIntegerConstant(int c, int index);
int jvmAddRealConstant(double c, int index);
void jvmWriteInfo(FILE *fp);
void jvmWriteInitMethod(FILE *fp);
void jvmWriteMainMethod(FILE *fp, nodeType *pTree, jvmHashTable **pHT);
void MakeOutputFileName(char *szInputFileName, char *szOutputFileName, char *szFileNameWithoutExt, char *szExt);
void jvmTypeCheck(int t1, int t2);
void MakeBytecodeMain(nodeType *p, jvmHashTable **pHT, Scope *pScope);
void jvmStart(char *szInputFileName, nodeType *pTree, Scope *pScope);

#endif /* JVM_H */


jvm.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "scanner.h"
#include "endianess.h"
#include "jvm.h"

/*#pragma warning(disable : 4996)*/

#define ARRAY_TO_S2(arr,v){ buff = (BYTE*)&v;\
FORMAT_WORD(arr,0);\
v = *( (S2*)arr ); }

#define ARRAY_TO_S4(arr,v){ buff = (BYTE*)&v;\
FORMAT_DWORD(arr,0);\
v = *( (S4*)arr ); }

#define ARRAY_TO_S8(arr,v){ buff = (BYTE*)&v;\
FORMAT_QWORD(arr,0);\
v = *( (S8*)arr ); }

#define ARRAY_TO_U2(arr,v){ buff = (BYTE*)&v;\
FORMAT_WORD(arr,0);\
v = *( (U2*)arr ); }

#define ARRAY_TO_U4(arr,v){ buff = (BYTE*)&v;\
FORMAT_DWORD(arr,0);\
v = *( (U4*)arr ); }

#define ARRAY_TO_U8(arr,v){ buff = (BYTE*)&v;\
FORMAT_QWORD(arr,0);\
v = *( (U8*)arr ); }

#define ARRAY_TO_F4(arr,v){ buff = (BYTE*)&v;\
FORMAT_DWORD(arr,0);\
v = *( (F4*)arr ); }

#define ARRAY_TO_F8(arr,v){ buff = (BYTE*)&v;\
FORMAT_QWORD(arr,0);\
v = *( (F8*)arr ); }

U2 g_ConstantPoolCount = 68;
/*U2 g_ConstantPoolCount = 13;*/
U1 g_ArrayConstantPool[4096];
U1 g_ArrayCode[4096];

int g_IndexConstantPool;
int g_IndexBytecodeArray = 0;

U2 g_max_stack = 0;
U2 g_max_locals = 1;
U4 g_code_length = 0;


/*-------------------------- HashTable -----------------------------------------*/


/*HashTable* htNewNode(char *Key, enumTipo0 t0, enumTipo1 t1, enumTipo2 t2, Valore v, char bInizializzato)*/
jvmHashTable* jvmhtNewNode(char *Key, unsigned short c)
{
jvmHashTable *n;

n = (jvmHashTable*)malloc(sizeof(jvmHashTable));

if( n == NULL )
return NULL;

n->Key = (char*)malloc(strlen(Key)+1);
if ( n->Key == NULL )
{
free(n);
return NULL;
}
strcpy(n->Key, Key);
n->c = c;
n->next = NULL;

return n;
}

/*int htFind(HashTable **pHashTable, char *Key, HashTable *pDati)*/
int jvmhtFind(jvmHashTable **pHashTable, char *Key, unsigned short *c)
{
int index = 0;
jvmHashTable *t;
int a = 31415;
/* int b = 27183; */
char szTemp[1024];
/*char *s = Key;*/
char *s = szTemp;

strcpy(szTemp, Key);

*c = 0;

for(; *s != '\0'; s++)
{
if ( *s == '\n' )
*s = ' ';
index = (a*index + *s) % JVM_HT_SIZE;
}
if ( index < 0 )
index *= -1;

t = pHashTable[index];
while ( t != NULL )
{
if ( strcmp(t->Key, Key) == 0 )
{
*c = t->c;
return 1;
}
t = t->next;
}

return 0;
}

/*void htInsert(HashTable **pHashTable, char *Key, enumTipo0 t0, enumTipo1 t1, enumTipo2 t2, Valore v, char bInizializzato)*/
void jvmhtInsert(jvmHashTable **pHashTable, char *Key, unsigned short c)
{
int index = 0;
jvmHashTable *t = NULL;
int a = 31415;
/* int b = 27183; */
char szTemp[1024];
/*char *s = Key;*/
char *s = szTemp;

strcpy(szTemp, Key);

for(; *s != '\0'; s++)
{
if ( *s == '\n' )
*s = ' ';
index = (a*index + *s) % JVM_HT_SIZE;
}
if ( index < 0 )
index *= -1;

t = pHashTable[index];
if ( t == NULL )
{
pHashTable[index] = jvmhtNewNode(Key, c);
return;
}

while ( t != NULL )
{
if ( strcmp(t->Key, Key) == 0 )
{
/*pHashTable[index]->pLista = ListAppend(pHashTable[index]->pLista, pos);*/
printf("\nErrore: La chiave %s e' gia' presente nella hashtable\n", Key);
return;
}
if ( t->next == NULL )
{
t->next = jvmhtNewNode(Key, c);
/*t = t->next;*/
/*t->next = NULL;*/
return;
}
t = t->next;
}
}

void jvmhtFree(jvmHashTable* first)
{
jvmHashTable *n1 = first, *n2;
while ( n1 != NULL )
{
n2 = n1->next;
if ( n1->Key )
{
free(n1->Key);
}
free(n1);
n1 = n2;
}
}

/*------------------------------ JVM ----------------------------------------------*/

void jvmSetNumberLocals(int n)
{
g_max_locals = n;
}

void jvmWriteHeader(FILE *fp)
{
U4 magic = 0xCAFEBABE;
U2 minor_version = 0;
U2 major_version = 50;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

if ( !isBigEndian() )
{
ARRAY_TO_U4(buff, magic);
ARRAY_TO_U2(buff, minor_version);
ARRAY_TO_U2(buff, major_version);
}

fwrite(&magic, sizeof(U4), 1, fp);
fwrite(&minor_version, sizeof(U2), 1, fp);
fwrite(&major_version, sizeof(U2), 1, fp);
}

int jvmMakeConstantPool(char *szSourceFile, char *szClassName)
{
int k;
int index = 0;
U1 tag;
U2 name_index;
U2 class_index;
U2 name_and_type_index;
U2 descriptor_index;
U2 length;
U2 lengthBigEndian;

char szStringa[1024];

U1 fb[8]; /*Necessario per usare le macro;*/
BYTE *buff;

tag = CONSTANT_Class;
for ( k = 25; k < 33; k++)
{
g_ArrayConstantPool[index++] = tag;
name_index = k;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
}
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
}

tag = CONSTANT_Fieldref;
class_index = 3;
name_and_type_index = 33;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;



tag = CONSTANT_Methodref;

class_index = 2;
name_and_type_index = 36;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 6;
name_and_type_index = 36;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 6;
name_and_type_index = 39;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 6;
name_and_type_index = 42;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 4;
name_and_type_index = 45;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 3;
name_and_type_index = 48;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 5;
name_and_type_index = 51;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 7;
name_and_type_index = 54;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

class_index = 8;
name_and_type_index = 57;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;




tag = CONSTANT_Utf8;

strcpy(szStringa, "Code");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "LineNumberTable");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "main");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "([Ljava/lang/String;)V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "SourceFile");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, szSourceFile);
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

/*strcpy(szStringa, "PrintDemo");*/
strcpy(szStringa, szClassName);
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/lang/Object");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/lang/System");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/io/PrintStream");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/io/Console");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/lang/StringBuilder");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/lang/Integer");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "java/lang/Double");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 34;
descriptor_index = 35;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "out");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "Ljava/io/PrintStream;");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 37;
descriptor_index = 38;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "<init>");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "()V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 40;
descriptor_index = 41;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "append");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 43;
descriptor_index = 44;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "toString");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "()Ljava/lang/String;");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 46;
descriptor_index = 47;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "print");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "(Ljava/lang/String;)V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 49;
descriptor_index = 50;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "console");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "()Ljava/io/Console;");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 52;
descriptor_index = 53;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "readLine");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "()Ljava/lang/String;");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 55;
descriptor_index = 56;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "parseInt");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "(Ljava/lang/String;)I");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_NameAndType;
name_index = 58;
descriptor_index = 59;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "parseDouble");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

strcpy(szStringa, "(Ljava/lang/String;)D");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;



/*---------------------- Aggiunti in seguito --------------------*/

tag = CONSTANT_Methodref;
class_index = 4;
name_and_type_index = 61;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

tag = CONSTANT_NameAndType;
name_index = 46;
descriptor_index = 62;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "(I)V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_Methodref;
class_index = 4;
name_and_type_index = 64;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

tag = CONSTANT_NameAndType;
name_index = 46;
descriptor_index = 65;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "(D)V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;


tag = CONSTANT_Methodref;
class_index = 4;
name_and_type_index = 67;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, class_index);
ARRAY_TO_U2(buff, name_and_type_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &class_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &name_and_type_index, 2);
index += 2;

tag = CONSTANT_NameAndType;
name_index = 46;
descriptor_index = 68;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
}
g_ArrayConstantPool[index++] = tag;
memcpy(g_ArrayConstantPool + index, &name_index, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, &descriptor_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szStringa, "(Z)V");
length = strlen(szStringa);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szStringa, length);
index += length;

return index;
}

int jvmAddArrayClass(int type, int sizes, int index)
{
char szClassName[512];
U1 tag;
U2 string_index;
U2 length;
U2 lengthBigEndian;

U1 fb[8]; /*Necessario per usare le macro;*/
BYTE *buff;

int k;

tag = CONSTANT_Class;
g_ArrayConstantPool[index++] = tag;
string_index = g_ConstantPoolCount + 2;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, string_index);
}
memcpy(g_ArrayConstantPool + index, &string_index, 2);
index += 2;

tag = CONSTANT_Utf8;
strcpy(szClassName, "[");
for ( k = 1; k < sizes; k++ )
{
strcat(szClassName, "[");
}
if ( type == T_INTEGER )
strcat(szClassName, "I");
if ( type == T_REAL )
strcat(szClassName, "D");
if ( type == T_BOOLEAN )
strcat(szClassName, "Z");
if ( type == T_STRING )
strcat(szClassName, "Ljava/lang/String;");
length = strlen(szClassName);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, szClassName, length);
index += length;

g_ConstantPoolCount += 2;

return index;
}


int jvmAddStringConstant(char *sz, int index)
{
U1 tag;
U2 string_index;
U2 length;
U2 lengthBigEndian;

U1 fb[8]; /*Necessario per usare le macro;*/
BYTE *buff;

tag = CONSTANT_String;
g_ArrayConstantPool[index++] = tag;
string_index = g_ConstantPoolCount + 2;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, string_index);
}
memcpy(g_ArrayConstantPool + index, &string_index, 2);
index += 2;

tag = CONSTANT_Utf8;
length = strlen(sz);
lengthBigEndian = length;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, lengthBigEndian);
}
memcpy(g_ArrayConstantPool + index, &lengthBigEndian, 2);
index += 2;
memcpy(g_ArrayConstantPool + index, sz, length);
index += length;

g_ConstantPoolCount += 2;

return index;
}

int jvmAddIntegerConstant(int c, int index)
{
U1 tag;
U4 bytes = (U4)c;

U1 fb[8]; /*Necessario per usare le macro;*/
BYTE *buff;

tag = CONSTANT_Integer;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_U4(buff, bytes);
}
memcpy(g_ArrayConstantPool + index, &bytes, 4);
index += 4;

g_ConstantPoolCount++;

return index;
}

int jvmAddRealConstant(double c, int index)
{
U1 tag;
F8 bytes = (F8)c;

U1 fb[8]; /*Necessario per usare le macro;*/
BYTE *buff;

tag = CONSTANT_Double;
g_ArrayConstantPool[index++] = tag;
if ( !isBigEndian() )
{
ARRAY_TO_F8(buff, bytes);
}
memcpy(g_ArrayConstantPool + index, &bytes, 8);
index += 8;

g_ConstantPoolCount += 2;

return index;
}

void jvmWriteInfo(FILE *fp)
{
U2 access_flags = ACC_SUPER;
U2 this_class = 1;
U2 super_class = 2;
U2 interfaces_count = 0;
U2 fields_count = 0;
U2 methods_count = 2;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, access_flags);
ARRAY_TO_U2(buff, this_class);
ARRAY_TO_U2(buff, super_class);
ARRAY_TO_U2(buff, interfaces_count);
ARRAY_TO_U2(buff, fields_count);
ARRAY_TO_U2(buff, methods_count);
}

fwrite(&access_flags, sizeof(U2), 1, fp);
fwrite(&this_class, sizeof(U2), 1, fp);
fwrite(&super_class, sizeof(U2), 1, fp);
fwrite(&interfaces_count, sizeof(U2), 1, fp);
fwrite(&fields_count, sizeof(U2), 1, fp);
fwrite(&methods_count, sizeof(U2), 1, fp);
}

void jvmWriteInitMethod(FILE *fp)
{
U1 bytecode;
U2 param;
U2 access_flags = 0;
U2 name_index = 37;
U2 descriptor_index = 38;
U2 attributes_count = 1;
U2 attribute_name_index = 19;
U4 attribute_length = 17;
U2 max_stack = 1;
U2 max_locals = 1;
U4 code_length = 5;
U2 exception_table_length = 0;
/*
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
*/
BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, access_flags);
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
ARRAY_TO_U2(buff, attributes_count);
ARRAY_TO_U2(buff, attribute_name_index);
ARRAY_TO_U4(buff, attribute_length);
ARRAY_TO_U2(buff, max_stack);
ARRAY_TO_U2(buff, max_locals);
ARRAY_TO_U4(buff, code_length);
}

fwrite(&access_flags, sizeof(U2), 1, fp);
fwrite(&name_index, sizeof(U2), 1, fp);
fwrite(&descriptor_index, sizeof(U2), 1, fp);
fwrite(&attributes_count, sizeof(U2), 1, fp);
fwrite(&attribute_name_index, sizeof(U2), 1, fp);
fwrite(&attribute_length, sizeof(U4), 1, fp);
fwrite(&max_stack, sizeof(U2), 1, fp);
fwrite(&max_locals, sizeof(U2), 1, fp);
fwrite(&code_length, sizeof(U4), 1, fp);

bytecode = jvm_aload_0;
fwrite(&bytecode, sizeof(U1), 1, fp);

bytecode = jvm_invokespecial;
fwrite(&bytecode, sizeof(U1), 1, fp);

param = 10; /*Method java/lang/Object."<init>":()V*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, param);
}
fwrite(&param, sizeof(U2), 1, fp);

bytecode = jvm_return;
fwrite(&bytecode, sizeof(U1), 1, fp);


exception_table_length = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, exception_table_length);
}
fwrite(&exception_table_length, sizeof(U2), 1, fp);

attributes_count = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, attributes_count);
}
fwrite(&attributes_count, sizeof(U2), 1, fp);
}

void jvmWriteMainMethod(FILE *fp, nodeType *pTree, jvmHashTable **pHT)
{
U2 access_flags = ACC_PUBLIC | ACC_STATIC;

U2 name_index = 21;
U2 descriptor_index = 22;

U2 attributes_count = 1;
U2 attribute_name_index = 19;

U4 attribute_length;
U4 code_lengthBigEndian;
U2 exception_table_length = 0;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, access_flags);
ARRAY_TO_U2(buff, name_index);
ARRAY_TO_U2(buff, descriptor_index);
ARRAY_TO_U2(buff, attributes_count);
ARRAY_TO_U2(buff, attribute_name_index);
}

fwrite(&access_flags, sizeof(U2), 1, fp);
fwrite(&name_index, sizeof(U2), 1, fp);
fwrite(&descriptor_index, sizeof(U2), 1, fp);
fwrite(&attributes_count, sizeof(U2), 1, fp);
fwrite(&attribute_name_index, sizeof(U2), 1, fp);

code_lengthBigEndian = g_code_length;

attribute_length = 12;
attribute_length += g_code_length;

if ( !isBigEndian() )
{
ARRAY_TO_U4(buff, attribute_length);
ARRAY_TO_U2(buff, g_max_stack);
ARRAY_TO_U2(buff, g_max_locals);
ARRAY_TO_U4(buff, code_lengthBigEndian);
}

fwrite(&attribute_length, sizeof(U4), 1, fp);
fwrite(&g_max_stack, sizeof(U2), 1, fp);
fwrite(&g_max_locals, sizeof(U2), 1, fp);
fwrite(&code_lengthBigEndian, sizeof(U4), 1, fp);

fwrite(g_ArrayCode, g_code_length, 1, fp);

exception_table_length = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, exception_table_length);
}
fwrite(&exception_table_length, sizeof(U2), 1, fp);

attributes_count = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, attributes_count);
}
fwrite(&attributes_count, sizeof(U2), 1, fp);
}

void MakeOutputFileName(char *szInputFileName, char *szOutputFileName, char *szFileNameWithoutExt, char *szExt)
{
int k;
int dotIndex;
int len = strlen(szInputFileName);

strcpy(szOutputFileName, "");
strcpy(szFileNameWithoutExt, "");
strcpy(szExt, "");

k = len - 1;

while ( k >= 0 )
{
if ( szInputFileName[k] == '.' )
break;
--k;
}
k++;

if ( k > 0 )
{
memcpy(szExt, szInputFileName + k, len - k);
szExt[len - k] = '\0';

k -= 2;
dotIndex = k + 1;
}
else
{
dotIndex = len;
}

while ( k >= 0 )
{
if ( !isalnum(szInputFileName[k]) && szInputFileName[k] != '_' )
break;
--k;
}
k++;

memcpy(szFileNameWithoutExt, szInputFileName + k, dotIndex - k);
szFileNameWithoutExt[dotIndex - k] = '\0';

strcpy(szOutputFileName, szFileNameWithoutExt);
strcat(szOutputFileName, ".class");
}

void MakeBytecodeDeclArrayMain(jvmHashTable **pHT, HashTable *pDati)
{
char szInt[128];
char szClassName[128];
int k;

U2 constClassIndex;
U1 constIntegerIndex;

U1 bytecode;
U1 paramU1;
U2 paramU2;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

HashTable *t = pDati;


for ( k = 0; k < t->Value.pArrayDef->countIndexes; k++ )
{
/* ************* INIZIO LOAD ****************** */

if ( t->Value.pArrayDef->sizes[k] >= -128 && t->Value.pArrayDef->sizes[k] <= 127 )
{
if ( t->Value.pArrayDef->sizes[k] >= -1 && t->Value.pArrayDef->sizes[k] <= 5 )
{
if ( t->Value.pArrayDef->sizes[k] == 0 )
bytecode = jvm_iconst_0;
else if ( t->Value.pArrayDef->sizes[k] == 1 )
bytecode = jvm_iconst_1;
else if ( t->Value.pArrayDef->sizes[k] == 2 )
bytecode = jvm_iconst_2;
else if ( t->Value.pArrayDef->sizes[k] == 3 )
bytecode = jvm_iconst_3;
else if ( t->Value.pArrayDef->sizes[k] == 4 )
bytecode = jvm_iconst_4;
else if ( t->Value.pArrayDef->sizes[k] == 5 )
bytecode = jvm_iconst_5;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
bytecode = jvm_bipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = (U1)t->Value.pArrayDef->sizes[k];
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
}
else if ( t->Value.pArrayDef->sizes[k] >= -32768 && t->Value.pArrayDef->sizes[k] <= 32767 )
{
bytecode = jvm_sipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = (U2)t->Value.pArrayDef->sizes[k];
if ( !isBigEndian() )
{
ARRAY_TO_S2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}
else
{
sprintf(szInt, "%d", t->Value.pArrayDef->sizes[k]);
if ( !jvmhtFind(pHT, szInt, (unsigned short*)&constIntegerIndex) )
{
constIntegerIndex = (unsigned char)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, szInt, constIntegerIndex);
g_IndexConstantPool = jvmAddIntegerConstant(t->Value.pArrayDef->sizes[k], g_IndexConstantPool);
}

bytecode = jvm_ldc;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = constIntegerIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
}

if ( t->Value.pArrayDef->countIndexes == 1 )
{
bytecode = jvm_newarray;

switch ( t->Tipo1 )
{
case T_INTEGER:
paramU1 = 10;
break;
case T_REAL:
paramU1 = 7;
break;
case T_BOOLEAN:
paramU1 = 4;
break;
case T_STRING:
paramU1 = 8; /*byte*/
break;
}

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;

/* ************* FINE LOAD ******************* */
}
else /*Array Multidimensionale*/
{
bytecode = jvm_multianewarray;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

strcpy(szClassName, "[");
for ( k = 1; k < t->Value.pArrayDef->countIndexes; k++ )
{
strcat(szClassName, "[");
}
if ( t->Tipo1 == T_INTEGER )
strcat(szClassName, "I");
if ( t->Tipo1 == T_REAL )
strcat(szClassName, "D");
if ( t->Tipo1 == T_BOOLEAN )
strcat(szClassName, "Z");
if ( t->Tipo1 == T_STRING )
strcat(szClassName, "Ljava/lang/String;");

if ( !jvmhtFind(pHT, szClassName, (unsigned short*)&constClassIndex) )
{
constClassIndex = (unsigned short)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, szClassName, constClassIndex);
g_IndexConstantPool = jvmAddArrayClass(t->Tipo1, t->Value.pArrayDef->countIndexes, g_IndexConstantPool);
}

paramU2 = constClassIndex;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU1 = (U1)t->Value.pArrayDef->countIndexes;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;

/* ************* FINE LOAD ****************** */
}


/* ************* INIZIO STORE **************** */
if (pDati->frameIndex >= 0 && pDati->frameIndex <= 3)
{
if ( (U1)pDati->frameIndex == 0 )
bytecode = jvm_astore_0;
else if ( (U1)pDati->frameIndex == 1 )
bytecode = jvm_astore_1;
else if ( (U1)pDati->frameIndex == 2 )
bytecode = jvm_astore_2;
else if ( (U1)pDati->frameIndex == 3 )
bytecode = jvm_astore_3;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack--;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
bytecode = jvm_astore;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack--;
g_code_length++;
g_IndexBytecodeArray++;
paramU1 = (U1)pDati->frameIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
/* ************* FINE STORE *************** */
}

void MakeBytecodeDeclInitMain(jvmHashTable **pHT, Scope *pScope)
{
int index;
HashTable *t;
HashTable **pHashTable;

HashTable Dati;

char szInt[128];
char szReal[128];

U1 constStringIndex;
U1 constIntegerIndex;
U2 constRealIndex;

U1 bytecode;
U1 paramU1;
U2 paramU2;

S1 paramS1;
S2 paramS2;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/


pHashTable = pScope->stack[0];

for ( index = 0; index < HT_SIZE - 1; index++ )
{
t = pHashTable[index];
while ( t != NULL )
{
scopeFind(pScope, t->Key, &Dati);

if ( t->Tipo0 == T_SIMPLE && t->bInizializzato && t->bDecl )
{
/* ************* INIZIO LOAD ******************* */

switch ( t->Tipo1 )
{
case T_INTEGER:
if ( t->Value.iVal >= -128 && t->Value.iVal <= 127 )
{
if ( t->Value.iVal >= -1 && t->Value.iVal <= 5 )
{
if ( t->Value.iVal == -1 )
bytecode = jvm_iconst_m1;
else if ( t->Value.iVal == 0 )
bytecode = jvm_iconst_0;
else if ( t->Value.iVal == 1 )
bytecode = jvm_iconst_1;
else if ( t->Value.iVal == 2 )
bytecode = jvm_iconst_2;
else if ( t->Value.iVal == 3 )
bytecode = jvm_iconst_3;
else if ( t->Value.iVal == 4 )
bytecode = jvm_iconst_4;
else if ( t->Value.iVal == 5 )
bytecode = jvm_iconst_5;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
bytecode = jvm_bipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramS1 = (S1)t->Value.iVal;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramS1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
}
else if ( t->Value.iVal >= -32768 && t->Value.iVal <= 32767 )
{
bytecode = jvm_sipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramS2 = (S2)t->Value.iVal;
if ( !isBigEndian() )
{
ARRAY_TO_S2(buff, paramS2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramS2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}
else
{
sprintf(szInt, "%d", t->Value.iVal);
if ( !jvmhtFind(pHT, szInt, (unsigned short*)&constIntegerIndex) )
{
constIntegerIndex = (unsigned char)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, szInt, constIntegerIndex);
g_IndexConstantPool = jvmAddIntegerConstant(t->Value.iVal, g_IndexConstantPool);
}

bytecode = jvm_ldc;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = constIntegerIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

break;
case T_REAL:
if ( t->Value.dblVal == 0.0 || t->Value.dblVal == 1.0 )
{
if ( t->Value.dblVal == 0.0 )
bytecode = jvm_dconst_0;
else if ( t->Value.dblVal == 1.0 )
bytecode = jvm_dconst_1;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack += 2;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
sprintf(szReal, "%lf", t->Value.dblVal);
if ( !jvmhtFind(pHT, szReal, &constRealIndex) )
{
constRealIndex = (unsigned short)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, szReal, constRealIndex);
g_IndexConstantPool = jvmAddRealConstant(t->Value.dblVal, g_IndexConstantPool);
}

bytecode = jvm_ldc2_w;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack += 2;
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = constRealIndex;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}

break;
case T_BOOLEAN:
if ( t->Value.bVal == 0 )
{
bytecode = jvm_iconst_0;
}
else if ( t->Value.bVal == 1 )
{
bytecode = jvm_iconst_1;
}

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

break;
case T_STRING:
if ( !jvmhtFind(pHT, t->Value.strVal, (unsigned short*)&constStringIndex) )
{
constStringIndex = (unsigned char)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, t->Value.strVal, constStringIndex);
g_IndexConstantPool = jvmAddStringConstant(t->Value.strVal, g_IndexConstantPool);
}

bytecode = jvm_ldc;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = constStringIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;

break;
}
/* ************* FINE LOAD ******************* */


/* ************* INIZIO STORE **************** */
if (Dati.frameIndex >= 0 && Dati.frameIndex <= 3)
{
if ( (U1)Dati.frameIndex == 0 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
bytecode = jvm_istore_0;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dstore_0;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_astore_0;
}
else if ( (U1)Dati.frameIndex == 1 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
bytecode = jvm_istore_1;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dstore_1;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_astore_1;
}
else if ( (U1)Dati.frameIndex == 2 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
bytecode = jvm_istore_2;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dstore_2;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_astore_2;
}
else if ( (U1)Dati.frameIndex == 3 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
bytecode = jvm_istore_3;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dstore_3;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_astore_3;
}

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
if ( Dati.Tipo1 != T_REAL )
g_max_stack--;
else
g_max_stack -= 2;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
bytecode = jvm_istore;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dstore;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_astore;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
if ( Dati.Tipo1 != T_REAL )
g_max_stack--;
else
g_max_stack -= 2;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = (U1)Dati.frameIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

/* ************* FINE STORE ************** */
}
else if ( t->Tipo0 == T_ARRAY )
{
MakeBytecodeDeclArrayMain(pHT, &Dati);
}

t = t->next;
}
}
}

void LoadArray(nodeType *p, jvmHashTable **pHT, Scope *pScope)
{
U1 bytecode;
U1 paramU1;

int k;

if ( p->type0 == T_ARRAY )
{
HashTable Dati;
scopeFind(pScope, p->id.name, &Dati);

if ( Dati.frameIndex >= 0 && Dati.frameIndex <= 3 )
{
if ( (U1)Dati.frameIndex == 0 )
bytecode = jvm_aload_0;
else if ( (U1)Dati.frameIndex == 1 )
bytecode = jvm_aload_1;
else if ( (U1)Dati.frameIndex == 2 )
bytecode = jvm_aload_2;
else if ( (U1)Dati.frameIndex == 3 )
bytecode = jvm_aload_3;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
bytecode = jvm_aload;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;
paramU1 = (U1)Dati.frameIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

MakeBytecodeMain(p->id.value.pArrayDef->indexes[0], pHT, pScope);

if ( p->id.value.pArrayDef->countIndexes > 1 )
{
for ( k = 1; k < p->id.value.pArrayDef->countIndexes; k++ )
{
bytecode = jvm_aaload;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

if ( p->id.value.pArrayDef )
MakeBytecodeMain(p->id.value.pArrayDef->indexes[k], pHT, pScope);
}
}
}
}

void jvmTypeCheck(int t1, int t2)
{
U1 bytecode;

if ( t1 == t2 )
return;

switch ( t1 )
{
case T_INTEGER:
if ( t2 == T_REAL )
bytecode = jvm_d2i;
break;
case T_REAL:
if ( t2 == T_INTEGER || t2 == T_BOOLEAN )
bytecode = jvm_i2d;
break;
case T_BOOLEAN:
if ( t2 == T_REAL )
bytecode = jvm_d2i;
break;
}

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

void MakeBytecodeMain(nodeType *p, jvmHashTable **pHT, Scope *pScope)
{
U1 constStringIndex;
U1 constIntegerIndex;
U2 constRealIndex;

U1 bytecode;
U1 paramU1;
U2 paramU2;

S1 paramS1;
S2 paramS2;

U2 segnaposto1, segnaposto2;

static int bLeftSide = 0;

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

if (!p)
{
return;
}

switch(p->type)
{
case typeConst:
{
switch( p->type1 )
{
case T_INTEGER:
if ( p->con.value.iVal >= -128 && p->con.value.iVal <= 127 )
{
if ( p->con.value.iVal >= -1 && p->con.value.iVal <= 5 )
{
if ( p->con.value.iVal == -1 )
bytecode = jvm_iconst_m1;
else if ( p->con.value.iVal == 0 )
bytecode = jvm_iconst_0;
else if ( p->con.value.iVal == 1 )
bytecode = jvm_iconst_1;
else if ( p->con.value.iVal == 2 )
bytecode = jvm_iconst_2;
else if ( p->con.value.iVal == 3 )
bytecode = jvm_iconst_3;
else if ( p->con.value.iVal == 4 )
bytecode = jvm_iconst_4;
else if ( p->con.value.iVal == 5 )
bytecode = jvm_iconst_5;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
bytecode = jvm_bipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramS1 = (S1)p->con.value.iVal;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramS1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
}
else if ( p->con.value.iVal >= -32768 && p->con.value.iVal <= 32767 )
{
bytecode = jvm_sipush;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramS2 = (S2)p->con.value.iVal;
if ( !isBigEndian() )
{
ARRAY_TO_S2(buff, paramS2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramS2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}
else
{
if ( !jvmhtFind(pHT, p->con.lexeme, (unsigned short*)&constIntegerIndex) )
{
constIntegerIndex = (unsigned char)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, p->con.lexeme, constIntegerIndex);
g_IndexConstantPool = jvmAddIntegerConstant(p->con.value.iVal, g_IndexConstantPool);
}

bytecode = jvm_ldc;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = constIntegerIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

break;
case T_REAL:
if ( p->con.value.dblVal == 0.0 || p->con.value.dblVal == 1.0 )
{
if ( p->con.value.dblVal == 0.0 )
bytecode = jvm_dconst_0;
else if ( p->con.value.dblVal == 1.0 )
bytecode = jvm_dconst_1;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack += 2;
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
if ( !jvmhtFind(pHT, p->con.lexeme, &constRealIndex) )
{
constRealIndex = (unsigned short)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, p->con.lexeme, constRealIndex);
g_IndexConstantPool = jvmAddRealConstant(p->con.value.dblVal, g_IndexConstantPool);
}

bytecode = jvm_ldc2_w;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack += 2;
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = constRealIndex;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}

break;
case T_BOOLEAN:
if ( p->con.value.bVal == 0 )
bytecode = jvm_iconst_0;
else if ( p->con.value.bVal == 1 )
bytecode = jvm_iconst_1;

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

break;
case T_STRING:
if ( !jvmhtFind(pHT, p->con.value.strVal, (unsigned short*)&constStringIndex) )
{
constStringIndex = (unsigned char)(g_ConstantPoolCount + 1);
jvmhtInsert(pHT, p->con.value.strVal, constStringIndex);
g_IndexConstantPool = jvmAddStringConstant(p->con.value.strVal, g_IndexConstantPool);
}

bytecode = jvm_ldc;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = constStringIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;

break;
}

return;
}
break;
case typeId:
{
HashTable Dati;
if ( scopeFind(pScope, p->id.name, &Dati) )
{
if ( Dati.Tipo0 == T_ARRAY )
{
if ( bLeftSide )
{
if ( Dati.Tipo1 == T_INTEGER )
bytecode = jvm_iastore;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_dastore;
else if ( Dati.Tipo1 == T_BOOLEAN )
bytecode = jvm_bastore;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_aastore;
}
else
{
if ( Dati.Tipo1 == T_INTEGER )
bytecode = jvm_iaload;
else if ( Dati.Tipo1 == T_REAL )
bytecode = jvm_daload;
else if ( Dati.Tipo1 == T_BOOLEAN )
bytecode = jvm_baload;
else if ( Dati.Tipo1 == T_STRING )
bytecode = jvm_aaload;
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
if ( bLeftSide )
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack--;
else
g_max_stack -= 2;
}
else
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack++;
else
g_max_stack += 2;
}
g_code_length++;
g_IndexBytecodeArray++;
}
else /*Dati.Tipo0 == T_SIMPLE*/
{
if (Dati.frameIndex >= 0 && Dati.frameIndex <= 3)
{
if ( (U1)Dati.frameIndex == 0 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
{
if ( bLeftSide )
bytecode = jvm_istore_0;
else
bytecode = jvm_iload_0;
}
else if ( Dati.Tipo1 == T_REAL )
{
if ( bLeftSide )
bytecode = jvm_dstore_0;
else
bytecode = jvm_dload_0;
}
else if ( Dati.Tipo1 == T_STRING )
{
if ( bLeftSide )
bytecode = jvm_astore_0;
else
bytecode = jvm_aload_0;
}
}
else if ( (U1)Dati.frameIndex == 1 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
{
if ( bLeftSide )
bytecode = jvm_istore_1;
else
bytecode = jvm_iload_1;
}
else if ( Dati.Tipo1 == T_REAL )
{
if ( bLeftSide )
bytecode = jvm_dstore_1;
else
bytecode = jvm_dload_1;
}
else if ( Dati.Tipo1 == T_STRING )
{
if ( bLeftSide )
bytecode = jvm_astore_1;
else
bytecode = jvm_aload_1;
}
}
else if ( (U1)Dati.frameIndex == 2 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
{
if ( bLeftSide )
bytecode = jvm_istore_2;
else
bytecode = jvm_iload_2;
}
else if ( Dati.Tipo1 == T_REAL )
{
if ( bLeftSide )
bytecode = jvm_dstore_2;
else
bytecode = jvm_dload_2;
}
else if ( Dati.Tipo1 == T_STRING )
{
if ( bLeftSide )
bytecode = jvm_astore_2;
else
bytecode = jvm_aload_2;
}
}
else if ( (U1)Dati.frameIndex == 3 )
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
{
if ( bLeftSide )
bytecode = jvm_istore_3;
else
bytecode = jvm_iload_3;
}
else if ( Dati.Tipo1 == T_REAL )
{
if ( bLeftSide )
bytecode = jvm_dstore_3;
else
bytecode = jvm_dload_3;
}
else if ( Dati.Tipo1 == T_STRING )
{
if ( bLeftSide )
bytecode = jvm_astore_3;
else
bytecode = jvm_aload_3;
}
}

memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
if ( bLeftSide )
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack--;
else
g_max_stack -= 2;
}
else
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack++;
else
g_max_stack += 2;
}
g_code_length++;
g_IndexBytecodeArray++;
}
else
{
if ( Dati.Tipo1 == T_INTEGER || Dati.Tipo1 == T_BOOLEAN)
{
if ( bLeftSide )
bytecode = jvm_istore;
else
bytecode = jvm_iload;
}
else if ( Dati.Tipo1 == T_REAL )
{
if ( bLeftSide )
bytecode = jvm_dstore;
else
bytecode = jvm_dload;
}
else if ( Dati.Tipo1 == T_STRING )
{
if ( bLeftSide )
bytecode = jvm_astore;
else
bytecode = jvm_aload;
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
if ( bLeftSide )
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack--;
else
g_max_stack -= 2;
}
else
{
if ( Dati.Tipo1 != T_REAL )
g_max_stack++;
else
g_max_stack += 2;
}
g_code_length++;
g_IndexBytecodeArray++;

paramU1 = (U1)Dati.frameIndex;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU1, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
}
}
else
{
printf("Errore: X identificatore '%s' non dichiarato\n", p->id.name);
}

return;
}
break;
case typeOperator:
{
switch(p->opr.oper)
{
case T_KW_WHILE:
segnaposto1 = g_IndexBytecodeArray;
MakeBytecodeMain(p->opr.op[0], pHT, pScope);

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_if_icmpeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

MakeBytecodeMain(p->opr.op[1], pHT, pScope);

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = segnaposto1 - g_IndexBytecodeArray + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);

return;
case T_KW_DO: /*do-while*/
segnaposto1 = g_IndexBytecodeArray;
MakeBytecodeMain(p->opr.op[1], pHT, pScope);

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_if_icmpeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

MakeBytecodeMain(p->opr.op[0], pHT, pScope);

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = segnaposto1 - g_IndexBytecodeArray + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);

return;
case T_KW_IF:
MakeBytecodeMain(p->opr.op[0], pHT, pScope);

if (p->opr.nops > 2)
{
/*if else*/
bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_if_icmpeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

MakeBytecodeMain(p->opr.op[1], pHT, pScope);

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto1 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);

MakeBytecodeMain(p->opr.op[2], pHT, pScope);

paramU2 = g_IndexBytecodeArray - segnaposto1 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto1, &paramU2, 2);
}
else
{
/*if*/
bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_if_icmpeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

MakeBytecodeMain(p->opr.op[1], pHT, pScope);

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);
}

return;
case T_KW_PRINT:
bytecode = jvm_getstatic;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 9; /*Field java/lang/System.out:Ljava/io/PrintStream;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

LoadArray(p->opr.op[0], pHT, pScope);

MakeBytecodeMain(p->opr.op[0], pHT, pScope);

bytecode = jvm_invokevirtual;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

if ( p->opr.op[0]->type1 == T_STRING )
paramU2 = 14; /*java/io/PrintStream.print:(Ljava/lang/String;)V*/
else if ( p->opr.op[0]->type1 == T_INTEGER )
paramU2 = 60; /*java/io/PrintStream.print:(I)V*/
else if ( p->opr.op[0]->type1 == T_REAL )
paramU2 = 63; /*java/io/PrintStream.print:(D)V*/
else if ( p->opr.op[0]->type1 == T_BOOLEAN )
paramU2 = 66; /*java/io/PrintStream.print:(Z)V*/

if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

return;
case T_KW_READ:
bytecode = jvm_invokestatic;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_max_stack++;
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 15; /*java/lang/System.console:()Ljava/io/Console;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_invokevirtual;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 16; /*java/io/Console.readLine:()Ljava/lang/String;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

if ( p->opr.op[0]->type1 != T_STRING )
{
bytecode = jvm_invokestatic;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

if ( p->opr.op[0]->type1 == T_INTEGER )
paramU2 = 17; /*java/lang/Integer.parseInt:(Ljava/lang/String;)I*/
else if ( p->opr.op[0]->type1 == T_REAL )
paramU2 = 18; /*java/lang/Double.parseDouble:(Ljava/lang/String;)D*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}

LoadArray(p->opr.op[0], pHT, pScope);
bLeftSide = 1;
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
bLeftSide = 0;

return;
case T_STMT_LIST:
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
return;
case T_CODE_BLOCK:
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
return;
case T_OP_ASSIGN:
LoadArray(p->opr.op[0], pHT, pScope);
LoadArray(p->opr.op[1], pHT, pScope);
bLeftSide = 0;
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->opr.op[0]->type1, p->opr.op[1]->type1);
bLeftSide = 1;
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
bLeftSide = 0;
return;
case T_OP_UMINUS:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);

if ( p->opr.op[0]->type1 == T_INTEGER )
bytecode = jvm_ineg;
else if ( p->opr.op[0]->type1 == T_REAL )
bytecode = jvm_dneg;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_PLUS:
if ( p->type1 != T_STRING )
{
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
bytecode = jvm_iadd;
else if ( p->type1 == T_REAL )
bytecode = jvm_dadd;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else /*Concatenazione di due stringhe*/
{
bytecode = jvm_new;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 6; /*class java/lang/StringBuilder*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_dup;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_invokespecial;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 11; /*java/lang/StringBuilder."<init>":()V*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);

bytecode = jvm_invokevirtual;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 12; /*java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);

bytecode = jvm_invokevirtual;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 12; /*java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_invokevirtual;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 13; /*java/lang/StringBuilder.toString:()Ljava/lang/String;*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;
}

return;
case T_OP_MINUS:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
bytecode = jvm_isub;
else if ( p->type1 == T_REAL )
bytecode = jvm_dsub;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_MULT:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
bytecode = jvm_imul;
else if ( p->type1 == T_REAL )
bytecode = jvm_dmul;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_DIV:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
bytecode = jvm_idiv;
else if ( p->type1 == T_REAL )
bytecode = jvm_ddiv;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_LT:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmpge;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpg;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_ifge;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_GT:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmple;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpl;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_ifle;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_GE:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmplt;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpl;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_iflt;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_LE:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmpgt;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpl;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_ifgt;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_NE:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmpeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpl;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_ifeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_EQ:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

if ( p->type1 == T_INTEGER )
{
bytecode = jvm_if_icmpne;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}
else if ( p->type1 == T_REAL )
{
bytecode = jvm_dcmpl;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_ifne;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
}

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_AND:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

bytecode = jvm_ifeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto1 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

bytecode = jvm_ifeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto1 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto1, &paramU2, 2);

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_OR:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

bytecode = jvm_ifne;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto1 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

LoadArray(p->opr.op[1], pHT, pScope);
MakeBytecodeMain(p->opr.op[1], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[1]->type1);

bytecode = jvm_ifeq;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;
segnaposto2 = g_IndexBytecodeArray;

paramU2 = 0;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto1 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto1, &paramU2, 2);

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

paramU2 = g_IndexBytecodeArray - segnaposto2 + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + segnaposto2, &paramU2, 2);

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
case T_OP_NOT:
LoadArray(p->opr.op[0], pHT, pScope);
MakeBytecodeMain(p->opr.op[0], pHT, pScope);
jvmTypeCheck(p->type1, p->opr.op[0]->type1);

bytecode = jvm_ifne;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 7; /*= 6 + 1 ( + 1 perchè comprende il byte dell'istruzione if_icmpge o ifge )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_1;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

bytecode = jvm_goto;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

paramU2 = 4; /*= 3 + 1 ( + 1 perchè comprende il byte dell'istruzione goto )*/
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, paramU2);
}
memcpy(g_ArrayCode + g_IndexBytecodeArray, &paramU2, 2);
g_code_length += 2;
g_IndexBytecodeArray += 2;

bytecode = jvm_iconst_0;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;
g_IndexBytecodeArray++;

return;
}
}
break;
}
}

void jvmStart(char *szInputFileName, nodeType *pTree, Scope *pScope)
{
FILE *fp;
U2 constant_pool_count;
U2 attributes_count = 0;
U1 bytecode;

char szOutputFileName[512];
char szFileNameWithoutExt[512];
char szExt[512];
char szSourceFile[512];
char szClassName[512];

BYTE *buff;
U1 fb[8]; /*Necessario per usare le macro;*/

jvmHashTable **pHT;
int x;

MakeOutputFileName(szInputFileName, szOutputFileName, szFileNameWithoutExt, szExt);
strcpy(szSourceFile, szFileNameWithoutExt);
strcat(szSourceFile, ".");
strcat(szSourceFile, szExt);

strcpy(szClassName, szFileNameWithoutExt);

fp = fopen(szOutputFileName, "wb");
if ( !fp )
{
printf("Errore. Impossibile creare il file %s.\n", szOutputFileName);
return;
}


pHT = (jvmHashTable**)malloc(sizeof(jvmHashTable*) * JVM_HT_SIZE);
if ( pHT != NULL )
{
for ( x = 0; x < JVM_HT_SIZE; x++ )
{
pHT[x] = (jvmHashTable*)malloc(sizeof(jvmHashTable));
if ( pHT[x] == NULL )
{
printf("Memoria non sufficiente.\n");
return;
}
pHT[x] = NULL;
}
}
else
{
printf("Memoria non sufficiente.\n");
return;
}

jvmWriteHeader(fp);
g_IndexConstantPool = jvmMakeConstantPool(szSourceFile, szClassName);

MakeBytecodeDeclInitMain(pHT, pScope);
MakeBytecodeMain(pTree, pHT, pScope);

bytecode = jvm_return;
memcpy(g_ArrayCode + g_IndexBytecodeArray, &bytecode, 1);
g_code_length++;


constant_pool_count = g_ConstantPoolCount + 1;
if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, constant_pool_count);
}
fwrite(&constant_pool_count, sizeof(U2), 1, fp);
fwrite(g_ArrayConstantPool, g_IndexConstantPool, 1, fp);

jvmWriteInfo(fp);
jvmWriteInitMethod(fp);
jvmWriteMainMethod(fp, pTree, pHT);

if ( !isBigEndian() )
{
ARRAY_TO_U2(buff, attributes_count);
}
fwrite(&attributes_count, sizeof(U2), 1, fp);

fclose(fp);

for ( x = 0; x < JVM_HT_SIZE; x++)
jvmhtFree(pHT[x]);
free(pHT);
}

The_ouroboros
23-02-2013, 10:07
Guardate cosa ho trovato....

Gcc Explorer (http://gcc.godbolt.org/)

Un sito che da il disasm del codice C che gli passi e permette anche un minimo di parametri :D

Vincenzo1968
23-02-2013, 10:18
Naturalmente nel contest 17 non s'è vista neanche l'ombra di python. Sempre tante belle chiacchiere: python questo, python quello, python è così, python è colà, python su, python giù, python a destra, python a sinistra, python sopra, python sotto... ma quando c'è da fare i fatti...

Non dico che non si potesse fare in python. Dico che i chiacchieroni, qui, non lo sanno fare.

Disiscritto dai. Disiscrivetevi anche voi. Disiscriviamoci tutti.

sottovento
23-02-2013, 10:40
Naturalmente nel contest 17 non s'è vista neanche l'ombra di python. Sempre tante belle chiacchiere: python questo, python quello, python è così, python è colà, python su, python giù, python a destra, python a sinistra, python sopra, python sotto... ma quando c'è da fare i fatti...

Non dico che non si potesse fare in python. Dico che i chiacchieroni, qui, non lo sanno fare.

Disiscritto dai. Disiscrivetevi anche voi. Disiscriviamoci tutti.

Scusa se ti rispondo, anche se evidentemente il messaggio era rivolto a qualcun altro.
Vincenzo, sei una brava persona ed un ottimo tecnico, anzi di piu'! E ne hai dato una gran dimostrazione su questo forum.
E' per questo che non capisco questo "sfogo", che esula dai motivi tecnici.
Non conosco python, ho solo letto qualcosa per avere un'infarinatura di base e mi sembra un ottimo linguaggio. Di chiacchieroni ce ne sono tanti, ma certamente non puoi chiamare chiacchierone quella persona a cui fai riferimento, poiche' anche lui e' un gran tecnico. Avete punti di vista diversi, entrambi condivisibili. Avreste entrambi solo da guadagnare dalla vostra amicizia, e tutto da perdere a farvi la guerra.

my two cents

Vincenzo1968
23-02-2013, 10:46
Per una volta che si decide di partecipare la qualità dei risultati lascia a desiderare:

http://img687.imageshack.us/img687/2703/c19b02classifica01.jpg

http://www.hwupgrade.org/public/style_emoticons/default/dumb.png

httpwwwliliberliber... :rotfl:

Ma python qua, python la, python su, python giù, python ha fatto questo, python ha fatto quello... e quanto fa schifo il C, e quant'è bello python...

Vincenzo1968
23-02-2013, 10:55
Scusa se ti rispondo, anche se evidentemente il messaggio era rivolto a qualcun altro.
Vincenzo, sei una brava persona ed un ottimo tecnico, anzi di piu'! E ne hai dato una gran dimostrazione su questo forum.
E' per questo che non capisco questo "sfogo", che esula dai motivi tecnici.
Non conosco python, ho solo letto qualcosa per avere un'infarinatura di base e mi sembra un ottimo linguaggio. Di chiacchieroni ce ne sono tanti, ma certamente non puoi chiamare chiacchierone quella persona a cui fai riferimento, poiche' anche lui e' un gran tecnico. Avete punti di vista diversi, entrambi condivisibili. Avreste entrambi solo da guadagnare dalla vostra amicizia, e tutto da perdere a farvi la guerra.

my two cents

No non sono un ottimo tecnico. Il codice non l'ho postato per fare vedere quanto sono bravo. L'ho postato per fare vedere chi fa i fatti e chi fa solo chiacchiere.

Io, come ho sempre detto, sono qui per imparare. Non mi sento e non sono bravo. Non sono per niente un ottimo tecnico.

Quando Gugo aprì i primi contest la cosa mi entusiasmò tantissimo(e vale anche per tanti altri utenti; basta andarseli a rivedere). Proprio perché c'era da imparare giocando.

Qui, in questo thread qualcuno ha approfittato dell'occasione, come fa sempre, per dire quanto fa schifo il C. E non fa critiche costruttive. Insulta, denigra. Giocare in maniera sporca coi puntatori...

Ma un po' di rispetto per chi ci lavora col C(il linguaggio, dico) no?

The_ouroboros
23-02-2013, 10:56
La velocità non è tutto.. la mantenibilità è ugual modo importante..

Vincenzo1968
23-02-2013, 10:59
Disiscriviti The_ouroboros. Che cacchio c'entra la velocità? Ho parlato di qualità dei risultati:

httpwwwliberliberitbibliotecalicenze... come lo giudichi qualitativamente?

Ma, dico, python non doveva essere il linguaggio per eccellenza per il problem solving?

Ragazzi, disiscriviamoci.

sottovento
23-02-2013, 11:15
No non sono un ottimo tecnico. Il codice non l'ho postato per fare vedere quanto sono bravo. L'ho postato per fare vedere chi fa i fatti e chi fa solo chiacchiere.

Io, come ho sempre detto, sono qui per imparare. Non mi sento e non sono bravo. Non sono per niente un ottimo tecnico.

Quando Gugo aprì i primi contest la cosa mi entusiasmò tantissimo(e vale anche per tanti altri utenti; basta andarseli a rivedere). Proprio perché c'era da imparare giocando.

Qui, in questo thread qualcuno ha approfittato dell'occasione, come fa sempre, per dire quanto fa schifo il C. E non fa critiche costruttive. Insulta, denigra. Giocare in maniera sporca coi puntatori...

Ma un po' di rispetto per chi ci lavora col C(il linguaggio, dico) no?

Lavoro anch'io tutti i giorni con il C, e sono anch'io uno di quelli che lo denigra. Passo la maggior parte del mio tempo a cercare crash, risolvere memory leak, rispondere a colleghi che dopo aver scritto tonnellate di codice non sanno cos'hanno scritto, e via dicendo.
Le critiche sono legittime, soprattutto se rivolte ad un linguaggio.
Anzi! La critica al linguaggio e' un complimento al tecnico che lo DEVE usare (ripeto: DEVE).

Ho scritto esattamente quello che penso su di te: sei un tecnico di prim'ordine, un'ottima persona e mi piacerebbe averti in team in un progetto. Ma hai il sangue caldo :) Nessuno, quanto meno in questo thread, ti aveva offeso, ma hai visto le critiche come offesa personale. Lui non ti aveva minimamente criticato, aveva criticato il linguaggio. Le tue, invece, erano offese mirate.

Devi ammettedere che cdimauro e' una risorsa preziosa in questo forum, esattamente come lo sei tu. Se ora a causa della vostra assurda inimicizia uno dei due si allontanasse... beh, il forum sarebbe sicuramente piu' povero.

Guarda che l'essere un professionista, soprattutto nel nostro campo, non e' solo un fatto tecnico. Anzi! La maggior parte delle volte i problemi non sono di natura tecnica, ma di rapporto tra le persone, soprattutto che lavorano tutte sullo stesso progetto e tutte sotto stress. TI chiedo di usare la stessa professionalita' anche qui e... dai, dovresti scusarti con lui.

Poi, se vuoi, puoi mandarmi delle panelle. Avevo la ragazza di Partinico, anni fa (vivevo in Italia, allora) e me le mandava in una borsa termica piena di ghiaccio, ma ahime', arrivavano sempre da buttar via...

The_ouroboros
23-02-2013, 11:19
Siamo tutti professionisti qui comportiamoci come tali:D

cdimauro
23-02-2013, 11:20
No no, quale maniera corretta di procedere? Vuoi babbiare? Sto giocando in maniera sporca coi puntatori!
Perché, quello che hai fatto come lo classifichi? Dimmelo tu a questo punto.
Non mi riferivo comunque alla bitfield. Dicevo in generale, sugli operatori bitwise. Se un software ha bisogno di memorizzare i dati su file in formato big endian, e tu sei su un sistema little endian, quella funzione ti serve per sapere se prima di salvare i dati sul file devi convertire da little endian a big endian.
É quello che ho fatto per il punto 3 del contest 17. Il bytecode della jvm dev'essere, secondo quanto riportato dalle specifiche, in formato big endian.
Ma coi campi di bit il discorso è diverso, e non puoi applicare quel codice.

A meno che non definisci i campi di bit come costanti (anziché usare le struct), ed effettui manualmente la conversione degli interi (perché a questo punto parliamo di interi, e non di bit field).
Ma gioco in maniera sporca coi puntatori... Uh! i puntatori!
Vedi sopra. Aspetto che mi dici come classifichi quell'operazione che hai fatto.

Peraltro esiste una soluzione molto più pulita per capire se il sistema in cui sta girando il codice è little o big endian...
Disiscritto dai.
Ma non lo fai mai. Quindi, almeno per coerenza, non scriverlo più. :read:
Se la memoria non mi inganna, partire da lsb e' standard. Per questo che il codice sopra deve (dovrebbe?) dare gli stessi risultati indipendentemente dall'endianness.
Qui (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf) c'è il draft dell'ISO C.

A pagina 114:

"An implementation may allocate anyaddressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified."
Eh no! Cmq l'endianness del bit field e' lo stesso dell'intero da cui ho prelevato l'indirizzo.
Non è detto che lo sia. Dipende dal compilatore, come dicevo, e com'è riportato nello standard. Puoi avere un sistema big-endian in cui il compilatore alloca i bit dall'LSB, oppure dall'MSB.
Ad ogni modo, siamo perfettamente d'accordo che affidare il funzionamento di un programma a questi dettagli e' da pazzi. Cosi' come siamo d'accordo che il C/C++ sia un linguaggio il cui utilizzo debba essere limitato ai casi strettamente necessari, if any.
Assolutamente d'accordo. Ma si possono usare quelle cose, se sei al corrente dell'implementazione del compilatore e dei dettagli della macchina. Lo si fa, per forza di cose, quando si lavora in ambito embedded, dove non si va troppo per il sottile.
Nel mio, 3. Dai, non siamo vecchi: siamo interessanti :D
:p
Naturalmente nel contest 17 non s'è vista neanche l'ombra di python. Sempre tante belle chiacchiere: python questo, python quello, python è così, python è colà, python su, python giù, python a destra, python a sinistra, python sopra, python sotto... ma quando c'è da fare i fatti...
Sei ossessionato. Il fanatismo è una brutta bestia.
Non dico che non si potesse fare in python.
Infatti lo si fa: PyPy è scritto in RPython, un sottoinsieme di Python, e genera virtual machine per diversi linguaggi.
Dico che i chiacchieroni, qui, non lo sanno fare.
Da quando hai il dono dell'onniscienza? Stai facendo il passo più lungo della gamba.

Visto che ti senti così esperto col C, trovami il modo di scoprire l'endianess di un sistema senza ricorrere alla porcata che hai scritto prima.
Disiscritto dai. Disiscrivetevi anche voi. Disiscriviamoci tutti.
Vediamo quando terrai fede alla tua parola. Da siciliano a quanto pare hai dimenticato il valore della parola data.
Scusa se ti rispondo, anche se evidentemente il messaggio era rivolto a qualcun altro.
Vincenzo, sei una brava persona ed un ottimo tecnico, anzi di piu'! E ne hai dato una gran dimostrazione su questo forum.
E' per questo che non capisco questo "sfogo", che esula dai motivi tecnici.
Non conosco python, ho solo letto qualcosa per avere un'infarinatura di base e mi sembra un ottimo linguaggio. Di chiacchieroni ce ne sono tanti, ma certamente non puoi chiamare chiacchierone quella persona a cui fai riferimento, poiche' anche lui e' un gran tecnico. Avete punti di vista diversi, entrambi condivisibili. Avreste entrambi solo da guadagnare dalla vostra amicizia, e tutto da perdere a farvi la guerra.

my two cents
Lascialo perdere. E' un fanatico integralista: se gli tocchi il C gli va il sangue alla testa, e perde il lume della ragione.

Poi sta sempre a misurarsela. Sarà un complesso d'inferiorità che coltiva per il fatto di essere un ragioniere e non un informatico.

I contest li tira fuori soltanto per quello: per la sua autoesaltazione, e dell'unico strumento che sa usare...
Per una volta che si decide di partecipare la qualità dei risultati lascia a desiderare:

http://img687.imageshack.us/img687/2703/c19b02classifica01.jpg

http://www.hwupgrade.org/public/style_emoticons/default/dumb.png

httpwwwliliberliber... :rotfl:

Ma python qua, python la, python su, python giù, python ha fatto questo, python ha fatto quello... e quanto fa schifo il C, e quant'è bello python...
Una soluzione elegante scritta in pochissimo tempo (peraltro non l'avevo scritta nemmeno io: io avevo soltanto fornito indicazioni, e ho corretto qualcosa), che fa il suo lavoro.

Sì, lo possiamo proprio dire: quant'è bello Python. :D

cdimauro
23-02-2013, 11:28
No non sono un ottimo tecnico. Il codice non l'ho postato per fare vedere quanto sono bravo. L'ho postato per fare vedere chi fa i fatti e chi fa solo chiacchiere.
Io preferisco perdere il mio tempo in progetti che m'interessano, se permetti.

Esempio: WPython (http://code.google.com/p/wpython2/). Toh, una virtual machine: chi l'avrebbe mai detto. :D

E i miei studi e ricerche in materia sono ormai citati quando si parla di macchine virtuali.

I tuoi contest, invece? Che contributo hanno dato all'umanità, se non per la tua mera soddisfazione e appagamento?
Qui, in questo thread qualcuno ha approfittato dell'occasione, come fa sempre, per dire quanto fa schifo il C. E non fa critiche costruttive. Insulta, denigra. Giocare in maniera sporca coi puntatori...

Ma un po' di rispetto per chi ci lavora col C(il linguaggio, dico) no?
Sei troppo fanatico con questo C, e vedi ogni critica, peraltro legittima, come un attacco alla tua persona.

Riprenditi.
La velocità non è tutto.. la mantenibilità è ugual modo importante..
Già.
Disiscriviti The_ouroboros. Che cacchio c'entra la velocità? Ho parlato di qualità dei risultati:

httpwwwliberliberitbibliotecalicenze... come lo giudichi qualitativamente?

Ma, dico, python non doveva essere il linguaggio per eccellenza per il problem solving?
E' quel che è stato fatto: problema risolto, in poco tempo, e in maniera elegante e manutenibile.
Ragazzi, disiscriviamoci.
Dai tu il buon esempio.
Lavoro anch'io tutti i giorni con il C, e sono anch'io uno di quelli che lo denigra. Passo la maggior parte del mio tempo a cercare crash, risolvere memory leak, rispondere a colleghi che dopo aver scritto tonnellate di codice non sanno cos'hanno scritto, e via dicendo.
Le critiche sono legittime, soprattutto se rivolte ad un linguaggio.
Anzi! La critica al linguaggio e' un complimento al tecnico che lo DEVE usare (ripeto: DEVE).

Ho scritto esattamente quello che penso su di te: sei un tecnico di prim'ordine, un'ottima persona e mi piacerebbe averti in team in un progetto. Ma hai il sangue caldo :) Nessuno, quanto meno in questo thread, ti aveva offeso, ma hai visto le critiche come offesa personale. Lui non ti aveva minimamente criticato, aveva criticato il linguaggio. Le tue, invece, erano offese mirate.

Devi ammettedere che cdimauro e' una risorsa preziosa in questo forum, esattamente come lo sei tu. Se ora a causa della vostra assurda inimicizia uno dei due si allontanasse... beh, il forum sarebbe sicuramente piu' povero.

Guarda che l'essere un professionista, soprattutto nel nostro campo, non e' solo un fatto tecnico. Anzi! La maggior parte delle volte i problemi non sono di natura tecnica, ma di rapporto tra le persone, soprattutto che lavorano tutte sullo stesso progetto e tutte sotto stress. TI chiedo di usare la stessa professionalita' anche qui e... dai, dovresti scusarti con lui.

Poi, se vuoi, puoi mandarmi delle panelle. Avevo la ragazza di Partinico, anni fa (vivevo in Italia, allora) e me le mandava in una borsa termica piena di ghiaccio, ma ahime', arrivavano sempre da buttar via...
Post da incorniciare.
Siamo tutti professionisti qui comportiamoci come tali:D
Il fanatismo è una brutta bestia.

sottovento
23-02-2013, 11:40
Qui (http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf) c'è il draft dell'ISO C.

A pagina 114:

"An implementation may allocate anyaddressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified."


Non ho certo la pretesa di conoscere le specifiche a memoria. Devo dire che questa mi ha davvero sorpreso, anzi di piu': ci sono rimasto male.
Il motivo? Semplice: e' sempre funzionato cosi', al punto che su molti progetti ho visto SPECIFICHE che utilizzavano la notazione in questione per indicare quale bit di quale parola la scheda hardware avrebbe comunicato l'informazione.

In effetti non ho mai visto alcun sistema che non funzionasse cosi'.
Quindi, non mi resta che cospargermi il capo di cenere ed ammettere l'errore.
Pero'... continuero' a leggere le specifiche che mi vengono sottoposte utilizzando la "convenzione" di cui abbiamo parlato :D

Grazie


PS. adesso vorrei rivolgerti le stesse parole che ho rivolto a Vincenzo, visto che ora sei passato anche tu ad attaccare sul piano personale.
Come ha detto The_ouroboros: comportatevi da professionisti quali siete!!

Vincenzo1968
23-02-2013, 11:47
Meno chiacchiere e più fatti.

Soluzione elegante... As usual, tante belle parole...

Io ho fatto un un favore a python e ai pythonisti(che sono giustamente tanti, qui) incitando più volte gli utenti a proporre una loro soluzione. Ho detto loro di fregarsene se i tempi fossero risultati maggiori delle soluzioni in C. Ho detto che la cosa importante era capire e discutere l'algoritmo utilizzato.

Tu, al contrario, non hai reso un gran servizio con la tua soluzione. Questo per la smania di far vedere quanto lo si ha corto(il codice, dico).
Sarebbero sicuramente bastate un paio di righe di codice in più per produrre risultati qualitativamente buoni. E invece niente...

E per scrivere due righe di codice non venitemi a parlare di impegni e mancanza di tempo. E anche l'argomento "non m'interessa, m'interesso di altre cose" non è valido. Visto che sei intervenuto potevi scriverle quelle due righe di codice in più. Nell'interesse dei tanti utenti che iniziano con python.

E invece niente, solo python qua, python la...

Disicriviamoci, sentite a me.

cdimauro
23-02-2013, 11:48
Non ho certo la pretesa di conoscere le specifiche a memoria. Devo dire che questa mi ha davvero sorpreso, anzi di piu': ci sono rimasto male.
Il motivo? Semplice: e' sempre funzionato cosi', al punto che su molti progetti ho visto SPECIFICHE che utilizzavano la notazione in questione per indicare quale bit di quale parola la scheda hardware avrebbe comunicato l'informazione.

In effetti non ho mai visto alcun sistema che non funzionasse cosi'.
Quindi, non mi resta che cospargermi il capo di cenere ed ammettere l'errore.
Pero'... continuero' a leggere le specifiche che mi vengono sottoposte utilizzando la "convenzione" di cui abbiamo parlato :D

Grazie
Ma nemmeno io ricordo tutte le specifiche, specialmente di tutti i linguaggi che conosco (nemmeno di Python, che è quello che uso più spesso adesso). :p

Semplicemente alcuni dettagli dello standard C li ricordavo in questo contesto. Tutto qui. :)
PS. adesso vorrei rivolgerti le stesse parole che ho rivolto a Vincenzo, visto che ora sei passato anche tu ad attaccare sul piano personale.
Come ha detto The_ouroboros: comportatevi da professionisti quali siete!!
OK, io non ho alcun problema a farlo.

cdimauro
23-02-2013, 11:51
Meno chiacchiere e più fatti.

Soluzione elegante... As usual, tante belle parole...

Io ho fatto un un favore a python e ai pythonisti(che sono giustamente tanti, qui) incitando più volte gli utenti a proporre una loro soluzione. Ho detto loro di fregarsene se i tempi fossero risultati maggiori delle soluzioni in C. Ho detto che la cosa importante era capire e discutere l'algoritmo utilizzato.

Tu, al contrario, non hai reso un gran servizio con la tua soluzione. Questo per la smania di far vedere quanto lo si ha corto(il codice, dico).
Sarebbero bastate sicuramente altre due righe di codice per produrre risultati qualitativamente buoni. E invece niente...
La "qualità" per te sarebbe? La velocità?

Cos'ha il mio codice che non va PER TE? Esponi pure...
E per scrivere due righe di codice non venitemi a parlare di impegni e mancanza di tempo. E anche l'argomento "non m'interessa, m'interesso di altre cose" non è valido. Visto che sei intervenuto potevi scriverle quelle due righe di codice in più. Nell'interesse dei tanti utenti che iniziano con python.
Come ti ho già detto, dedico il mio tempo a cose più interessanti.
E invece niente, solo python qua, python la...
Hai sempre parlato di problem solving. Ti è stato dimostrato come Python sia particolarmente indicato allo scopo.

Fattene una ragione.
Disicriviamoci, sentite a me.
Come già detto, dai il buon esempio. Se non ti piace stare qui, accomodati pure fuori e tieni finalmente fede alla tua parola.

Gli altri hanno una testa per pensare e prendere le decisioni che ritengono più opportune. Non hanno bisogno di un alcun consiglio da parte tua.

The_ouroboros
23-02-2013, 11:56
Ma nemmeno io ricordo tutte le specifiche, specialmente di tutti i linguaggi che conosco

A questo servono i libri.. e/o le reference web :fagiano:

Torniamo it che la discussione mi sembrava interessante? :stordita:

Vincenzo1968
23-02-2013, 11:59
La qualità per me sarebbe dire che la parola più lunga è "magnificentissimamente" e non "httpwwwliberlibercazzivariscusiantanilasupercazzolaprematurataconscappellamentoadestra".

Ecco il codice python:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

def Main():

def fileSize(f):

f.seek(0, 2)
result = f.tell()
f.seek(0)

return result

currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''

with open(sys.argv[1], 'r') as f:
chars = fileSize(f)

for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line

list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word

f.close()

print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)


Vediamo se qualcuno riesce a fornire una versione qualitativamente buona. Magari ci vorrà provare The_ouroboros, repentinamente convertitosi da perl a python.
E magari, quando, come fai spesso, comincerai a parlar male di Linux, si convertirà, altrettanto repentinamente, a Windows, definitivamente abbandonando vi, vim e cazzi vari.

The_ouroboros
23-02-2013, 12:06
Ho solo cominciato ad apprezzare python come strumento per un fine come apprezzo e uso perl,c,java o pl/sql..

The_ouroboros
23-02-2013, 12:12
qualitativamente buono non vuol dire nulla. in un ambiente professionale vengono date delle specifiche e dei vincoli. un codice che implementa le specifiche correttamente e soddisfa quei vincoli ed è scritto nel tempo minore possibile ed è più facile da mantenere è l'obiettivo di qualsiasi azienda che abbia necessità di basso time to market.

Questo intendevo per fine:stordita:

Vincenzo1968
23-02-2013, 12:22
Le specifiche le avevo date. Avevo fatto notare a Vicius che la sua soluzione in JavaScript dava un risultato qualitativamente non buono. Trovava infatti:

"------------------------------------------------------------------------------------"

come parola più lunga.
Poi era intervenuto un utente(mi scuso ma non ricordo il nickname) a chiedere di chiarire cosa s'intendesse per qualitativamente buono.
Io avevo risposto che bisognava trovare parole della lingua italiana, e lui: "ma allora bisogna utilizzare un qualche dizionario?". E io "no, anche perché dove ce lo procuriamo? quindi al limite andrebbero bene anche parole come 'kjhtrfg' che non appartiene alla lingua italiana ma è almeno formata da caratteri alfabetici".

Ora, la parola trovata dal codice python è "httpwwwliberliberit..." che è evidentemente il link "http:/www.liberliber.it..." scevro dai caratteri di punteggiatura e '/'.

Vi sembra qualitativamente buona come soluzione?

Vi sembra un buon esempio di "problem solving"?

Vincenzo1968
23-02-2013, 12:26
Ho solo cominciato ad apprezzare python come strumento per un fine come apprezzo e uso perl,c,java o pl/sql..

Fatti dire di quando aggredì una povera ragazza(eventualmente ho il link), appena iscritta, solo perché si era permessa di fare una battuta su Windows(winzozz). Cionci, allora moderatore di questa sezione del forum, fu costretto a chiudere il thread.

Eh già, solo lui le può fare le battutine...

cdimauro
23-02-2013, 12:40
A questo servono i libri.. e/o le reference web :fagiano:
Infatti. Non possiamo mica ricordare tutto.
Torniamo it che la discussione mi sembrava interessante? :stordita:
D'accordo.
La qualità per me sarebbe dire che la parola più lunga è "magnificentissimamente" e non "httpwwwliberlibercazzivariscusiantanilasupercazzolaprematurataconscappellamentoadestra".

Ecco il codice python:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

def Main():

def fileSize(f):

f.seek(0, 2)
result = f.tell()
f.seek(0)

return result

currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''

with open(sys.argv[1], 'r') as f:
chars = fileSize(f)

for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line

list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word

f.close()

print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)


Vediamo se qualcuno riesce a fornire una versione qualitativamente buona. Magari ci vorrà provare The_ouroboros, repentinamente convertitosi da perl a python.
Questa versione che hai riportato, sulla base delle specifiche che TU avevi rilasciato all'epoca, soddisfaceva i requisiti del problema.

Dunque era "qualitativamente buona".
E magari, quando, come fai spesso, comincerai a parlar male di Linux, si convertirà, altrettanto repentinamente, a Windows, definitivamente abbandonando vi, vim e cazzi vari.
La polemica ce l'hai nel sangue.
Ho solo cominciato ad apprezzare python come strumento per un fine come apprezzo e uso perl,c,java o pl/sql..
Esatto. Sono tutti strumenti. Li si utilizza in base al problema da risolvere, quale "miglior" compromesso.
qualitativamente buono non vuol dire nulla. in un ambiente professionale vengono date delle specifiche e dei vincoli. un codice che implementa le specifiche correttamente e soddisfa quei vincoli ed è scritto nel tempo minore possibile ed è più facile da mantenere è l'obiettivo di qualsiasi azienda che abbia necessità di basso time to market.
Assolutamente d'accordo. E' il "comandamento" che ogni buon programmatore dovrebbe seguire.
Le specifiche le avevo date. Avevo fatto notare a Vicius che la sua soluzione in JavaScript dava un risultato qualitativamente non buono. Trovava infatti:

"------------------------------------------------------------------------------------"

come parola più lunga.
Poi era intervenuto un utente(mi scuso ma non ricordo il nickname) a chiedere di chiarire cosa s'intendesse per qualitativamente buono.
Io avevo risposto che bisognava trovare parole della lingua italiana, e lui: "ma allora bisogna utilizzare un qualche dizionario?". E io "no, anche perché dove ce l'ho procuriamo? quindi al limite andrebbero bene anche parole come 'kjhtrfg' che non appartiene alla lingua italiana ma è almeno formata da caratteri alfabetici".

Ora, la parola trovata dal codice python è "httpwwwliberliberit..." che è evidentemente il link "http:/www.liberliber.it..." scevro dai caratteri di punteggiatura e '/'.

Vi sembra qualitativamente buona come soluzione?

Vi sembra un buon esempio di "problem solving"?
Sì, se le specifiche sono soddisfatte. Soltanto DOPO le hai cambiate, e ti ho postato il codice aggiornato (che fa uso del metodo translate) e che soddisfaceva i NUOVI requisiti.

Dunque di cosa stiamo parlando? Chiacchiere. I fatti sono che le versioni postate soddisfacevano i requisiti posti all'epoca della loro scrittura.
Fatti dire di quando aggredì una povera ragazza(eventualmente ho il link), appena iscritta, solo perché si era permessa di fare una battuta su Windows(winzozz). Cionci, allora moderatore di questa sezione del forum, fu costretto a chiudere il thread.
Posta pure il link, così chiunque potrà valutare il contesto in cui ciò è avvenuto (che peraltro io nemmeno ricordo, quindi una rinfrescata non può che farmi bene).
Eh già, solo lui le può fare le battutine...
Le può fare chiunque, ovviamente, ma c'è un'enorme differenza con uno che si lascia andare sul personale perché si sente ferito e attaccato da una critica legittimissima a un linguaggio di programmazione.

Facci sapere quando hai intenzione di tornare a fare il professionista e discutere senza farti trascinare dall'emotività. Nella vita bisogna anche imparare a essere freddi e calcolatori quando si affrontano dei problemi.

Infine, sono rimaste in sospeso alcune cose che ti avevo fatto notare:
- il codice che avevi scritto sul rilevamento dell'endianess lo ritieni pulito oppure no?
- sei in grado di tirare fuori del codice più pulito per fare la stessa cosa?
- il tuo codice di rilevamento dell'endianess lo trovi compatibile con l'utilizzo dei campi di bit definibili con la sintassi del C? E se sì, come?

Vincenzo1968
23-02-2013, 12:42
Si ma, nella fretta, avevo scritto "dove ce l'ho procuriamo" che, a proposito della ingua italiana, è un orrore.

Vincenzo1968
23-02-2013, 12:47
Posta pure il link, così chiunque potrà valutare il contesto in cui ciò è avvenuto (che peraltro io nemmeno ricordo, quindi una rinfrescata non può che farmi bene).

Nome utente: Policchia.

Ti dice niente? Se non ti dovesse dire niente disiscriviti, senti a me.

Quello che tu giudicavi un tuo "caro amico", l'utente 71752(o qualcosa di simile, non ricordo il nick esatto), che successivamente è stato bannato perché aveva il vizio di insultare pesantemente gli utenti Linux(e non) ti dice niente?

Ma quale contesto, ma che vuoi contestualizzare?

sottovento
23-02-2013, 12:51
Ma nemmeno io ricordo tutte le specifiche, specialmente di tutti i linguaggi che conosco (nemmeno di Python, che è quello che uso più spesso adesso). :p

Semplicemente alcuni dettagli dello standard C li ricordavo in questo contesto. Tutto qui. :)


Scusa, non fraintendermi. Quello che intendevo e' che questa cosa e' cosi' consolidata nel mio ambiente da essere addirittura usata come specifica (non sto scherzando) di funzionamento da uffici diversi e fra aziende diverse. Quindi quando l'ho appresa ho avuto un mancamento. Tutto qui
Anzi no, non sono ancora riuscito a capacitarmene, ma e' un problema mio

Vincenzo1968
23-02-2013, 12:53
http://www.hwupgrade.it/forum/showthread.php?t=1837086

By Cionci:

Penso che una persona possa benissimo avere le proprie idee sui sistemi operativi senza per questo essere aggredita. Manco vi avesse offeso un parente. Anche io penso che Vista sia assolutamente pachidermico e tale da rendere lenti portatili dual core con 2 GB di Ram e voglio essere libero di poterlo continuare a pensare senza essere tacciato di eresia.

Chiudo questo thread, visto che non rispetta il regolamento di sezione per i titoli: http://www.hwupgrade.it/forum/showthread.php?t=1649196
Invito Policchia ad aprire un altro thread con un titolo appropriato al linguaggio per cui cerca il software per le metriche.


Amen.

Vincenzo1968
23-02-2013, 12:58
70104 o come si chiamava è stato bannato per ben altri motivi, per quanto ricordo.

Il motivo preciso non lo conosco ma fu più volte sospeso da Cionci per pesanti insulti. Ti devo postare i link?

cdimauro
23-02-2013, 13:01
Posta pure il link, così chiunque potrà valutare il contesto in cui ciò è avvenuto (che peraltro io nemmeno ricordo, quindi una rinfrescata non può che farmi bene).

Nome utente: Policchia.

Ti dice niente?
No.
Se non ti dovesse dire niente disiscriviti, senti a me.
Perché dovrei farlo? Fino a prova contraria sei tu che ripeti di volerti disiscrivere, ma non lo fai mai. Da "buon siciliano" che mantiene la parola data...

Inoltre, come già detto, non me lo ricordo. Non so come fartelo capire. Ci provo di nuovo:
NON ME LO RICORDO!
E chiaro questa volta?

Posta il link, e fammi leggere la discussione, così vediamo com'è andata.
Quello che tu giudicavi un tuo "caro amico", l'utente 71752(o qualcosa di simile, non ricordo il nick esatto), che successivamente è stato bannato perché aveva il vizio di insultare pesantemente gli utenti Linux(e non) ti dice niente?
Sì, Alberto. Il nick era diverso, ma ho capito.

Riguardo al ban, ricordi malissimo, invece: è stato fatto per altri motivi. cionci può darti ampie spiegazioni in merito, SE lo riterrà opportuno, visto che s'era verificata una brutta situazione.

Io non posso dirti il motivo. Ma non è quello che hai detto. Assolutamente.
Ma quale contesto, ma che vuoi contestualizzare?
Visto che ti capita spesso di "dimenticare" il contesto delle frasi dette, che ami estrapolare e tagliare a tuo piacimento, se permetti vorrei leggermi tutto il thread e vedere esattamente cos'accadde.

Si tratta, peraltro, di una richiesta legittima, visto che sei TU ad accusarmi di alcune cose, e ritengo di avere tutto il diritto di potermi difendere dalle tue infamanti accuse.
Scusa, non fraintendermi. Quello che intendevo e' che questa cosa e' cosi' consolidata nel mio ambiente da essere addirittura usata come specifica (non sto scherzando) di funzionamento da uffici diversi e fra aziende diverse. Quindi quando l'ho appresa ho avuto un mancamento. Tutto qui
Anzi no, non sono ancora riuscito a capacitarmene, ma e' un problema mio
Ho capito. :)

Vincenzo1968
23-02-2013, 13:04
Disiscriviti. Disiscriviamoci. Disiscrivetevi.

cdimauro
23-02-2013, 13:05
http://www.hwupgrade.it/forum/showthread.php?t=1837086

By Cionci:

Penso che una persona possa benissimo avere le proprie idee sui sistemi operativi senza per questo essere aggredita. Manco vi avesse offeso un parente. Anche io penso che Vista sia assolutamente pachidermico e tale da rendere lenti portatili dual core con 2 GB di Ram e voglio essere libero di poterlo continuare a pensare senza essere tacciato di eresia.

Chiudo questo thread, visto che non rispetta il regolamento di sezione per i titoli: http://www.hwupgrade.it/forum/showthread.php?t=1649196
Invito Policchia ad aprire un altro thread con un titolo appropriato al linguaggio per cui cerca il software per le metriche.


Amen.
Sì, adesso lo ricordo. Tutto qui? Io confermo quanto avevo scritto prima: bisogna vedere il contesto della discussione. E il contesto è ben chiaro.

Non cambio assolutamente una virgola di quel che ho scritto all'epoca. Contesto alla mano, appunto.
Disiscriviti. Disiscriviamoci. Disiscrivetevi.
Ma parla per te. Soprattutto: AGISCI!

Vincenzo1968
23-02-2013, 13:08
E tu, così, pensi di ricevere una risposta? E, per soprammercato, ci mette pure la faccina: :rolleyes:

Solo lui le può fare le "battutine pungenti". Gli altri no, gli altri si meritano la faccina :rolleyes:

cdimauro
23-02-2013, 13:12
E tu, così, pensi di ricevere una risposta? E, per soprammercato, ci mette pure la faccina: :rolleyes:

Solo lui le può fare le "battutine pungenti". Gli altri no, gli altri si meritano la faccina :rolleyes:
Ma di quale battuta parli? Io ero serissimo!

Quell'utente s'è posta in malo modo, e ho sottolineato che con quelle premesse avrebbe pure voluto delle risposte? :read:

E' tutto messo nero su bianco: basta leggere la discussione dall'inizio. Peraltro non ero nemmeno il solo a pensarla così, e no, non c'era soltanto Alberto a farglielo notare, ma anche altri utenti. Chissà perché: tutti intolleranti e dalla battuta acida?

Comunque: perché sei ancora qui? Disiscriviti. Via, su, perché perdere tempo per cose inutili?

Vincenzo1968
23-02-2013, 13:19
Intanto io mi riferivo alla battuta di Policchia: "winzozz".

Uh! s'è posta in malo modo! Gli altri si pongono in malo modo. Quando lui dice che il C fa schifo, che fa piangere, che fa ridere, non si pone in malo modo, no.
Le sue sono battutine graziose, pungenti magari, acide magari, ma pur sempre battutine graziose.
Gli altri invece non si possono minimamente permettere di criticare windows chiamandolo winzozz... Si pongono in malo modo...

Disiscriviamoci. :O

cdimauro
23-02-2013, 13:23
Intanto io mi riferivo ala battuta di Policchia: "winzozz".
Che non era una battuta. Rileggitelo meglio il thread, che ne hai bisogno.
Uh! s'è posta in malo modo! Gli altri si pongono in malo modo. Quando lui dice che il C fa schifo, che fa piangere, che fa ridere, non si pone in malo modo, no.
Ancora col C? Ma soffri di manie di persecuzione? Di un complesso d'inferiorità? Del complesso del "compratore", che deve difendere con le unghie e coi denti il proprio "acquisto"?
Le sue sono battutine graziose, pungenti magari, acide magari, ma pur sempre battutine graziose.
Nessuna battuta. Ero serissimo.
Gli altri invece non si possono minimamente permettere di criticare windows chiamandolo winzozz... Si pongono in malo modo...
Il thread è lì, visto che hai riportato il link: chiunque potrà giudicare come stanno le cose.
Disiscriviamoci. :O
Sei un disco incantato.

Invece perché non ritorni in topic, e rispondi a quelle questioni che avevo posto? Non dirmi che come "esperto" di C non sei in grado di farlo... :O

Fatti, e non chiacchiere. Oops: chissà chi lo diceva. :D

Vincenzo1968
23-02-2013, 13:31
"Esperto" del C non mi sono mai proclamato. Non mi sono mai proclamato esperto di niente. È sempre stato il contrario. Ho sempre ripetuto che sono qui per imparare.

A caratteri cubitali: "non me lo ricordo!".

Adesso tocca a te fornire almeno un link. Vediamo.

La questione del thread era se i bitwise fossero ancora oggi utili o no. E ho abbondantemente risposto con degli esempi di codice anche.

Per le questioni che poni tu, ti imito: "non m'interessa, ho altre cose a cui pensare, non me ne frega niente, ho da fare, non posso perdere tempo appresso alle tue questioni".

Disiscrivation. :O

cdimauro
23-02-2013, 13:38
"Esperto" del C non mi sono mai proclamato. Non mi sono mai proclamato esperto di niente. È sempre stato il contrario. Ho sempre ripetuto che sono qui per imparare.

A caratteri cubitali: "non me lo ricordo!".

Adesso tocca a te fornire almeno un link. Vediamo.
L'ho messo tra virgolette apposta. :cool:
La questione del thread era se i bitwise fossero ancora oggi utili o no. E ho abbondantemente risposto con degli esempi di codice anche.
Il tuo codice coi bit field del C non funziona, come avevo scritto. Confermi?
Per le questioni che poni tu, ti imito: "non m'interessa, ho altre cose a cui pensare, non me ne frega niente, ho da fare, non posso perdere tempo appresso alle tue questioni".
Bene. Allora non ti lamentare se qualcuno dirà che quel codice è sporco. :read:

In alternativa, puoi sempre dimostrare il contrario, ma... non lo fai. "Stranamente". :read:
Disiscrivation. :O
:nonsifa:

Vincenzo1968
23-02-2013, 13:51
Vabbuò dai mi disiscrivo.

Mi disiscrivo, dico, da questo thread. So che a qualcuno piacerebbe che mi disiscrivessi dal forum, ma no, dal thread dico. ;)

Disiscritto dai.

P.S.: ho fatto la richiesta, nel thread apposito e nell'interesse generale dei tanti programmatori python che si avvicinano per la prima volta a questo bel linguaggio, di azzizare la versione python per il contest 19. Speriamo di vedere una versione qualitativamente buona.

Ci vediamo ;)

cdimauro
23-02-2013, 13:57
Ti ho già detto che la versione in Python di quel contest soddisfaceva i requisiti che ALL'EPOCA avevi specificato. DOPO che hai modificato i requisiti, ti ho postato la versione aggiornata che, ancora una volta, soddisfaceva i NUOVI requisiti.

Fino a prova contraria, che peraltro non hai ancora fornito nonostante le richieste in merito, quel codice è "qualitativamente buono" e ha soddisfatto in maniera semplice, elegante, e in poco tempo il problema in oggetto. Problem... solved!

Adesso direi ritornare in topic. Continuiamo sull'apposito thread per il contest, se hai ancora da dire sull'argomento.
E qui sui campi di bit, per i quali, come già ripetuto diverse volte, la tua soluzione non risolve assolutamente il problema dell'endianess. Ribadisco: riguarda i bit field, definiti con l'apposita sintassi del C, come si stava discutendo in quel preciso contesto (sì, il contesto è importante).

Vincenzo1968
23-02-2013, 14:00
httpwwwliberliber...

mah! problem solved. mah! e poi mah! e poi di nuovo mah!

Comunque consiglierei di leggere "Il Contesto" di Leonardo Sciascia.

Ci vediamo(se volete) di la. ;)

cdimauro
23-02-2013, 14:04
Ti ho già risposto di là, e mostrato che il messaggio #665 del thread conteneva già la soluzione (una riga di codice da aggiungere, un'altra da sostituire) al problema, DOPO che avevi cambiato i requisiti. Come già detto. :read:

The_ouroboros
23-02-2013, 16:55
Cusiosità: sintassi Intel o AT&T?

cdimauro
23-02-2013, 17:07
Cusiosità: sintassi Intel o AT&T?
Intel tutta la vita. Quella AT&T è stata sviluppata per i compilatori, non per gli esseri umani.

The_ouroboros
23-02-2013, 17:11
Intel tutta la vita. Quella AT&T è stata sviluppata per i compilatori, non per gli esseri umani.

io le uso entrambe per non limitarmi ma devo dire che a forza di vederla la AT&T non mi spiace più come prima.
I vari l,b,w sono comodi.
Forse il posizionamento degli offset è scomodo a prima vista


Intel Syntax

instr foo,segreg:

mov eax,[ebx+20h]

add eax,[ebx+ecx*2h

lea eax,[ebx+ecx]

sub eax,[ebx+ecx*4h-20h]



[B]AT&T Syntax

instr %segreg:disp(base,index,scale),foo

movl 0x20(%ebx),%eax

addl (%ebx,%ecx,0x2),%eax

leal (%ebx,%ecx),%eax

subl -0x20(%ebx,%ecx,0x4),%eax

sottovento
23-02-2013, 17:13
Allora non sono l'unico!!!


//TCP Header structure as per RFC 793
struct tcphdr {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */
#endif
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)

u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};


Sembra che, chi usa i bitfield, consideri che si parta sempre da lsb.
Nel codice copiato, si fa la distinzione fra big endian/little endian ma non e' che faccia senso, visto che definiscono 8 bit.

Tornando a bomba sui linguaggi ad alto livello pascal/python/modula 2/...: come diceva cdimauro, i set hanno una implementazione piu' "matematica", corrispondente agli insiemi.
I bitfield e le operazioni di masking del C, no! Questo perche' sono fatte in primis per l'accesso all'hardware, cosa che certamente i linguaggi citati non prevedono

The_ouroboros
23-02-2013, 17:15
Nel codice copiato, si fa la distinzione fra big endian/little endian ma non e' che faccia senso, visto che definiscono 8 bit.


Ha senso dai 16bit in su in effetti:D

The_ouroboros
23-02-2013, 17:16
Tornando a bomba sui linguaggi ad alto livello pascal/python/modula 2/...: come diceva cdimauro, i set hanno una implementazione piu' "matematica", corrispondente agli insiemi.
I bitfield e le operazioni di masking del C, no! Questo perche' sono fatte in primis per l'accesso all'hardware, cosa che certamente i linguaggi citati non prevedono

Sono a + alto livello del C, quindi + astratti...
Il C è quasi un asm astratto a mio parere :fagiano:

cdimauro
23-02-2013, 17:29
io le uso entrambe per non limitarmi ma devo dire che a forza di vederla la AT&T non mi spiace più come prima.
I vari l,b,w sono comodi.
Forse il posizionamento degli offset è scomodo a prima vista


Intel Syntax

instr foo,segreg:

mov eax,[ebx+20h]

add eax,[ebx+ecx*2h

lea eax,[ebx+ecx]

sub eax,[ebx+ecx*4h-20h]


[B]AT&T Syntax

instr %segreg:disp(base,index,scale),foo

movl 0x20(%ebx),%eax

addl (%ebx,%ecx,0x2),%eax

leal (%ebx,%ecx),%eax

subl -0x20(%ebx,%ecx,0x4),%eax

Sarà questione di abitudine, ma trovo orribile e poco leggibile la sintassi AT&T.

Visto che hai tirato in ballo i suffissi, beh, sono inutili! Se specifichi che il registro di destinazione è eax, è già evidente che sto usando un long. Avrebbe senso per la memoria, ma se la sorgente è eax, la destinazione sarà a 32 bit... Con gli immediati il discorso cambierebbe, ma nel codice più frequente il suffisso nella sintassi AT&T è superfluo.
Allora non sono l'unico!!!
:D

//TCP Header structure as per RFC 793
struct tcphdr {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */
#endif
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)

u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};


Sembra che, chi usa i bitfield, consideri che si parta sempre da lsb.
Nel codice copiato, si fa la distinzione fra big endian/little endian ma non e' che faccia senso, visto che definiscono 8 bit.
Avrebbe senso soltanto se il compilatore partisse dall' MSB anziché dall'LSB.

Per il resto, con 8 bit l'endianess c'entra poco.
Tornando a bomba sui linguaggi ad alto livello pascal/python/modula 2/...: come diceva cdimauro, i set hanno una implementazione piu' "matematica", corrispondente agli insiemi.
Per questo si apprezzano di più: sono più comodi e intuitivi.
I bitfield e le operazioni di masking del C, no! Questo perche' sono fatte in primis per l'accesso all'hardware, cosa che certamente i linguaggi citati non prevedono
Già: è di più di basso livello.
Sono a + alto livello del C, quindi + astratti...
Il C è quasi un asm astratto a mio parere :fagiano:
Per questo viene considerato come linguaggio di medio-basso livello.

The_ouroboros
23-02-2013, 17:36
Sarà questione di abitudine, ma trovo orribile e poco leggibile la sintassi AT&T.

Visto che hai tirato in ballo i suffissi, beh, sono inutili! Se specifichi che il registro di destinazione è eax, è già evidente che sto usando un long. Avrebbe senso per la memoria, ma se la sorgente è eax, la destinazione sarà a 32 bit... Con gli immediati il discorso cambierebbe, ma nel codice più frequente il suffisso nella sintassi AT&T è superfluo.



Dato che si trovano entrambi... e nel mondo *nix AT&T è lo standard :stordita:

cdimauro
23-02-2013, 17:51
Capisco, ma c'è da spararsi a lavorare con quella sintassi. Lavorare in assembly è già un martirio: figuriamoci in quelle condizioni.

Io, ad esempio, non ho apprezzato nemmeno la sintassi "classica", e almeno per 65C02 e PIC Microchip ho realizzato delle mie versioni di assembly ad alto livello, che mi consentono di scrivere codice di basso livello, ma in maniera più pratica e comoda.

sottovento
23-02-2013, 18:00
Avrebbe senso soltanto se il compilatore partisse dall' MSB anziché dall'LSB.

Non proprio: partisse dall'msb occorrerebbe specificare anche quale e' il bit piu' significativo nell'intervallo! In pratica, si avrebbe una pericolosissima inversione del peso dei bit. Questo spiega perche', nonostante lo standard non dica nulla sulla allocazione dei bit, partono tutti da lsb.


Per il resto, con 8 bit l'endianess c'entra poco.

Giustissimo


Per questo si apprezzano di più: sono più comodi e intuitivi.

Giusto, pero' se quel bit serve ad accendere la lavatrice, con linguaggi a piu' alto livello resti con la biancheria sporca ;)


Già: è di più di basso livello.

Per questo viene considerato come linguaggio di medio-basso livello.

Di pure basso livello senza paura, ed andrebbe trattato come tale, anche se spesso non succede.

Allora, guardando in giro posso dire: cdimauro ha ragione su tutta la linea, non esiste assolutamente uno standard. Tuttavia a causa di evidenti limitazioni nella soluzione opposta, l'allocazione partendo da lsb e' uno standard de-facto. Sempre che, con il linguaggio C, si possa parlare di standard

The_ouroboros
23-02-2013, 18:00
Capisco, ma c'è da spararsi a lavorare con quella sintassi. Lavorare in assembly è già un martirio: figuriamoci in quelle condizioni.


Dato che al momento è più un "lavoro" di debugging e lavoro principalmente su piattaforma *nix mi sono adattato.

C'è solo vantaggio a leggerle entrambe.

Cmq, uscendo un po dal seminato, sto dando un occhio ad ARM... non male come ABI, pi+ semplice di x86/x64 ma, per alcune operazioni, molto veloce.

The_ouroboros
23-02-2013, 18:03
Allora, guardando in giro posso dire: cdimauro ha ragione su tutta la linea, non esiste assolutamente uno standard. Tuttavia a causa di evidenti limitazioni nella soluzione opposta, l'allocazione partendo da lsb e' uno standard de-facto. Sempre che, con il linguaggio C, si possa parlare di standard

consuetudine diffusa? :stordita:

The_ouroboros
23-02-2013, 18:07
Io, ad esempio, non ho apprezzato nemmeno la sintassi "classica", e almeno per 65C02 e PIC Microchip ho realizzato delle mie versioni di assembly ad alto livello, che mi consentono di scrivere codice di basso livello, ma in maniera più pratica e comoda.

Ma che bruta roba (http://skilldrick.github.com/easy6502/) :eek:

marco.r
23-02-2013, 18:44
Sono a casa in malattia e la mente divaga...
Il pensiero mi è ricaduto a qualche giorno fa quando debuggavo un programma e mi è sorta una domanda..
Chi usa ancora, con le moderne pipeline dei processori, le Bitwise operations?

Nel senso, a parte gli ambiente embedded, ovvio :D

Invero mi sa che, sempre con i moderni processori, anche usare lo xorg per swappare registri senza appoggio non sia tanto conveniente..

Proprio perche' operano bit a bit, le operazioni bitwise permettono due cose interessanti: applicare la stessa operazione su piu' bit (ovviamente) e operare su una sola parte del numero.

Il primo fatto vuol dire che se io ho una qualsiasi informazioni che riesco a rappresentare con un numero limitato di bit posso fare la stessa operazione contemporaneamente su piu' valori.
Quello degli insiemi di interi di cui si parlava prima e' un esempio. Posso rappresentare un insieme di piccoli numeri (<64 su una macchina a 64bit) con un singolo intero. Operazioni come intersezione o unione si fanno con una unica operazione bitwise. Una rappresentazione con una lista di numeri richiede molte piu' operazioni. A seconda del contesto questo potrebbe fare la differenza. La cosa si puo' estendere semplicemente ad insiemi piu' grandi.

Il secondo fatto vuol dire che io posso rappresentare piu' informazioni su un unico intero. Questo diventa molto comodo quando voglio trasferire dell'informazione e mi interessa minimizzare lo spazio utilizzato. Un esempio pratico sono i flag su un header di un pacchetto TCP (o anche IP), visto che posso usare un singolo bit per rappresentare il valore attivo o meno del flag. Le operazioni bitwise mi serviranno per estrarre il valore del singolo flag.

Un'altra applicazione e' quella di aggiungere delle informazioni ai puntatori in linguaggio di programmazione. In questo caso lo scopo e' quello di evitare una doppia reindirezione piuttosto che limitare l'uso della memoria.
Pensa ad un linguaggio di programmazione dinamico, come puo' essere ruby. Come faccio a rappresentare un numero intero e a distinguerlo da un oggetto vero e proprio quando lo passo a funzioni e metodi ? Una possibilita' e' di farne il cosidetto boxing e usare un oggetto per tenerne il contenuto vero e proprio, col problema che pero' nella migliore delle ipotesi raddoppio la memoria utilizzata. Con un linguaggio statico posso sapere a priori che e' un numero e quindi passare come argomento direttamente il valore.

Oppure posso sfruttare il fatto che solitamente la memoria che alloco allineato alla parola, per cui su macchine a 32 bit avro' i due bit piu' bassi sempre a 0. Perche' non sfruttarli per tenere delle informazioni aggiuntive ? Ad esempio potrei decidere che se metto 01 invece che 00 so che si tratta di un numero, usando un po' di shifting prima/dopo le operazioni sui numeri.

Storicamente, nei GC mark-and-sweep e compagnia, si usava un bit per la marcatura del puntatore durante la fase di mark.

Insomma esempi di uso se ne trovano a bizzeffe.

The_ouroboros
23-02-2013, 18:53
bellissimo intervento che offre ottimi spunti, grazie :)

cdimauro
24-02-2013, 07:36
Non proprio: partisse dall'msb occorrerebbe specificare anche quale e' il bit piu' significativo nell'intervallo! In pratica, si avrebbe una pericolosissima inversione del peso dei bit. Questo spiega perche', nonostante lo standard non dica nulla sulla allocazione dei bit, partono tutti da lsb.
Esatto: nulla è specificato nello standard, ma viene utilizzata una soluzione perché, all'atto pratico, una decisione la si deve pur prendere.
Giusto, pero' se quel bit serve ad accendere la lavatrice, con linguaggi a piu' alto livello resti con la biancheria sporca ;)
Questo dipende tutto dall'implementazione. Come dicevo, col Turbo Pascal era ben specificato com'era implementato il tipo "set of", per cui non c'erano sorprese e si poteva usare tranquillamente per mappare qualunque cosa, anche i registri hardware.
Lo stesso vale per il Modula-2 e il suo bitset.

La differenza, rispetto al C, è che questi linguaggi offrono un meccanismo più comodo e di alto livello per fare sostanzialmente le stesse cose.
Di pure basso livello senza paura, ed andrebbe trattato come tale, anche se spesso non succede.

Allora, guardando in giro posso dire: cdimauro ha ragione su tutta la linea, non esiste assolutamente uno standard. Tuttavia a causa di evidenti limitazioni nella soluzione opposta, l'allocazione partendo da lsb e' uno standard de-facto. Sempre che, con il linguaggio C, si possa parlare di standard
Beh, uno standard c'è, e ti dirò: trovo pure giusto che certi dettagli vengano lasciati all'implementazione del linguaggio.
Dato che al momento è più un "lavoro" di debugging e lavoro principalmente su piattaforma *nix mi sono adattato.

C'è solo vantaggio a leggerle entrambe.
Indubbiamente.
Cmq, uscendo un po dal seminato, sto dando un occhio ad ARM... non male come ABI, pi+ semplice di x86/x64 ma, per alcune operazioni, molto veloce.
x64 è molto simile ad ARM come ABI.

Quest'ultima ha un vantaggio nelle chiamate al kernel, soprattutto grazie al fatto che viene effettuato il banking dei registri, per cui ci si trova con dei registri immediatamente utilizzabili (senza doverli salvare prima nello stack, ad esempio).
Ma che bruta roba (http://skilldrick.github.com/easy6502/) :eek:
Beh, brutta proprio no, se consideri che parliamo di un processore estremamente vecchio e a 8 bit (http://www.appuntidigitali.it/2684/mos-6502-un-microprocessore-semplice-ma-cisc/). C'ho speso parecchio tempo, e mi sono pure divertito all'epoca.
Proprio perche' operano bit a bit, le operazioni bitwise permettono due cose interessanti: applicare la stessa operazione su piu' bit (ovviamente) e operare su una sola parte del numero.

Il primo fatto vuol dire che se io ho una qualsiasi informazioni che riesco a rappresentare con un numero limitato di bit posso fare la stessa operazione contemporaneamente su piu' valori.
Quello degli insiemi di interi di cui si parlava prima e' un esempio. Posso rappresentare un insieme di piccoli numeri (<64 su una macchina a 64bit) con un singolo intero. Operazioni come intersezione o unione si fanno con una unica operazione bitwise. Una rappresentazione con una lista di numeri richiede molte piu' operazioni. A seconda del contesto questo potrebbe fare la differenza. La cosa si puo' estendere semplicemente ad insiemi piu' grandi.

Il secondo fatto vuol dire che io posso rappresentare piu' informazioni su un unico intero. Questo diventa molto comodo quando voglio trasferire dell'informazione e mi interessa minimizzare lo spazio utilizzato. Un esempio pratico sono i flag su un header di un pacchetto TCP (o anche IP), visto che posso usare un singolo bit per rappresentare il valore attivo o meno del flag. Le operazioni bitwise mi serviranno per estrarre il valore del singolo flag.

Un'altra applicazione e' quella di aggiungere delle informazioni ai puntatori in linguaggio di programmazione. In questo caso lo scopo e' quello di evitare una doppia reindirezione piuttosto che limitare l'uso della memoria.
Pensa ad un linguaggio di programmazione dinamico, come puo' essere ruby. Come faccio a rappresentare un numero intero e a distinguerlo da un oggetto vero e proprio quando lo passo a funzioni e metodi ? Una possibilita' e' di farne il cosidetto boxing e usare un oggetto per tenerne il contenuto vero e proprio, col problema che pero' nella migliore delle ipotesi raddoppio la memoria utilizzata. Con un linguaggio statico posso sapere a priori che e' un numero e quindi passare come argomento direttamente il valore.

Oppure posso sfruttare il fatto che solitamente la memoria che alloco allineato alla parola, per cui su macchine a 32 bit avro' i due bit piu' bassi sempre a 0. Perche' non sfruttarli per tenere delle informazioni aggiuntive ? Ad esempio potrei decidere che se metto 01 invece che 00 so che si tratta di un numero, usando un po' di shifting prima/dopo le operazioni sui numeri.

Storicamente, nei GC mark-and-sweep e compagnia, si usava un bit per la marcatura del puntatore durante la fase di mark.

Insomma esempi di uso se ne trovano a bizzeffe.
Sì, infatti, sono estremamente utili, specialmente smanettando a basso livello.

Quella di utilizzare i bit bassi di un puntatore per indicare il tipo dell'oggetto oppure la presenza di un intero o altro, la cullo da tempo per la virtual machine di Python. Ne abbiamo parlato con un altro paio di core dev che lavorano sulla virtual machine, all'ultima EuroPython, ma il problema più grosso è che si tratta di una modifica enorme, che impatterebbe praticamente tutto.

L'idea è concreta, visto che i puntatori sono tutti allineati almeno a 8 byte (e a 16 per le architetture a 64 bit; adesso non ricordo bene, però), per cui i primi 3 bit (bassi) sono sempre a zero e potrebbero essere utilmente impiegati per specificare immediatamente il tipo.

C'è, però, da pagare il prezzo del masking per ogni operazione: per ripulire i 3 bit bassi quando si è in presenza di un puntatore vero e proprio, e per eliminarli del tutto se abbiamo un intero. Questa cosa si deve fare ogni volta che si deve manipolare il puntatore o l'intero, ed è questo il deterrente principale nell'utilizzo di questa tecnica.

In ARM64 è stata fatta una cosa molto utile, a cui ho pensato da molto tempo che si potesse applicare a x64: l'uso degli 8 bit alti dei puntatore come tag. In pratica il processore taglia via in automatico gli 8 bit alti ogni volta che usa un puntatore per referenziare la memoria, realizzando in hardware quello che, invece, dovremmo implementare in software. Il fatto che siano ben 8 bit sarebbe molto comodo perché consentirebbe di specificare diversi tipi di dati.

Spero che AMD o Intel facciano la stessa con le future implementazioni di x64: sono anni che lo auspico. Tanto il futuro è rappresentato da macchine a 64 bit, e questa sarebbe un'utilissima funzionalità.

The_ouroboros
24-02-2013, 08:47
In ARM64 è stata fatta una cosa molto utile, a cui ho pensato da molto tempo che si potesse applicare a x64: l'uso degli 8 bit alti dei puntatore come tag. In pratica il processore taglia via in automatico gli 8 bit alti ogni volta che usa un puntatore per referenziare la memoria, realizzando in hardware quello che, invece, dovremmo implementare in software. Il fatto che siano ben 8 bit sarebbe molto comodo perché consentirebbe di specificare diversi tipi di dati.

Spero che AMD o Intel facciano la stessa con le future implementazioni di x64: sono anni che lo auspico. Tanto il futuro è rappresentato da macchine a 64 bit, e questa sarebbe un'utilissima funzionalità.


In effetti ARM diventa sempre più interessante come architettura :D

cdimauro
24-02-2013, 09:02
Se riscrivi completamente l'architettura, beh, puoi fare quello che vuoi (e anche di meglio, te l'assicuro :fagiano: ).

ARM64 della vecchia ARM ha mantenuto soltanto il nome. Poi, ok, è in grado di eseguire il vecchio codice, ma ARM ha introdotto una nuova modalità d'esecuzione a 64 bit, e con un'ISA anch'essa completamente diversa.

Per rendere l'idea, è simile a quanto ha fatto AMD con x64. Anche se AMD è stata molto meno drastica (perché ha mantenuto la vecchia opcode table, cambiando un po' di cose).

The_ouroboros
24-02-2013, 09:08
a volte la rottura totale e la scelta migliore.
Non si può supportare a vita con retrocompatibilità.:D

P.S: ARM64 clean and elegant (http://www.tgdaily.com/hardware-features/65536-analyst-arms-64-bit-architecture-is-clean-and-elegant) and ARM goes 64bit (più specifico) (http://www.realworldtech.com/arm64/)

cdimauro
24-02-2013, 09:28
ARM64 la conosco abbastanza. :fagiano: I link me li leggo appena posso.

Comunque è "clean" perché riprogettata da zero. Ma hanno dovuto fare delle scelte di compromesso (infatti hanno buttato via alcuni pilastri della vecchia architettura ARM).

Però è anche "fat": opcode soltanto a 32 bit. Mentre ARM aveva tirato fuori quelli a 16-32 bit con Thumb/2, e che aiutavano molto ad aumentare la densità di codice.

The_ouroboros
24-02-2013, 09:31
ARM64 la conosco abbastanza. :fagiano: I link me li leggo appena posso.

Comunque è "clean" perché riprogettata da zero. Ma hanno dovuto fare delle scelte di compromesso (infatti hanno buttato via alcuni pilastri della vecchia architettura ARM).

Però è anche "fat": opcode soltanto a 32 bit. Mentre ARM aveva tirato fuori quelli a 16-32 bit con Thumb/2, e che aiutavano molto ad aumentare la densità di codice.

I link erano per me in primis e per gli altri interessati...anzi se na hai altri scrivi pure :cool:
Ma non credo ci troverai nulla di nuovo :D

Thumb/2 mi aveva sempre incuriosito ai tempi di quando mi sono interessato agli smartphone android/ios :stordita:

P.S: Modalità Thumb: ad ARM si sono ristretti… gli opcode! (http://www.appuntidigitali.it/4814/modalita-thumb-ad-arm-si-sono-ristretti-gli-opcode/) e Thumb/2 (Con Thumb-2 ARM tradisce i RISC e ritorna… ai CISC! ) (http://www.appuntidigitali.it/4947/con-thumb-2-arm-tradisce-i-risc-e-ritorna-ai-cisc/)

cdimauro
24-02-2013, 10:34
Thumb/2 è molto usata proprio per ridurre la dimensione del codice, ed è molto importante proprio in dispositivi come smarthphone e tablet (ma anche sistemi embedded e microcontrollori). Ecco perché ha avuto un notevole successo.

Purtroppo di altri link sull'ARM64 non saprei cosa darti.

marco.r
24-02-2013, 18:51
C'è, però, da pagare il prezzo del masking per ogni operazione: per ripulire i 3 bit bassi quando si è in presenza di un puntatore vero e proprio, e per eliminarli del tutto se abbiamo un intero. Questa cosa si deve fare ogni volta che si deve manipolare il puntatore o l'intero, ed è questo il deterrente principale nell'utilizzo di questa tecnica.

In teoria con una oculata scelta dei tag si dovrebbe un po' ridurre il prezzo da pagare.
Supponendo di utilizzare 4 bit per i tag, uso il pattern 0000 e 1000 per (rispettivamente) interi pari e dispari: la somma rimane invariata, per la moltiplicazione mi basta un preshift di uno dei due operandi di 3 bit etc.
Mi rimane da ripulire il puntatore nel caso sia un puntatore vero e proprio, ma alla fine nessuna alternativa e' piu' economica... se non devo ripulire dovro' aggiungere un offset (per la parola successiva) etc.

sottovento
25-02-2013, 05:18
Questo dipende tutto dall'implementazione. Come dicevo, col Turbo Pascal era ben specificato com'era implementato il tipo "set of", per cui non c'erano sorprese e si poteva usare tranquillamente per mappare qualunque cosa, anche i registri hardware.
Lo stesso vale per il Modula-2 e il suo bitset.


Continuo a non capire. Prendi un set, per esempio (da wikipedia, voce "Turbo Pascal"):

var
Set1 : set of 1..10;
Set2 : set of 'a'..'z';
Set3 : set of Pear..Orange;


Come fai a vederci una mappatura con un registro hardware, per esempio? Inoltre per il set valgono le operazioni insiemistiche, non quelle a bit! Come hai giustamente detto, i set sono un'astrazione, somigliano alle classiche operazioni matematiche, ma perdono ovviamente il contatto con l'hardware e le operazioni a basso livello necessarie per comandarlo.
E' un problema? Direi di no: a ognuno il suo, quindi la parte low level sara' implementata con un linguaggio a basso livello, come il C; poi il resto dell'applicazione sara' fatta con un linguaggio a piu' alto livello. Ma non riesco proprio a vedere come le operazioni di set possano mappare, per esempio, i bit di un registro. Esiste un'altra estensione, tipo il Pascal che veniva usato sui Macintosh ai tempi del system 6?

cdimauro
25-02-2013, 07:04
In teoria con una oculata scelta dei tag si dovrebbe un po' ridurre il prezzo da pagare.
Supponendo di utilizzare 4 bit per i tag, uso il pattern 0000 e 1000 per (rispettivamente) interi pari e dispari: la somma rimane invariata, per la moltiplicazione mi basta un preshift di uno dei due operandi di 3 bit etc.
Mi rimane da ripulire il puntatore nel caso sia un puntatore vero e proprio, ma alla fine nessuna alternativa e' piu' economica... se non devo ripulire dovro' aggiungere un offset (per la parola successiva) etc.
La soluzione di miglior compromesso che avevo trovato è stata quella di usare la seguente configurazione (usando i 3 bit bassi):
tag ab0 -> puntatore a oggetti;
tag xx1 -> intero di 31 bit (o 63 bit per macchine a 64 bit);

ab = 2 bit per specificare il tipo noto.
00 -> oggetto generico;
01 -> intero (più lungo del precedente);
10 -> double;
11 -> stringa.

Il vantaggio di questa configurazione è che per riconoscere se è un intero "compatto" basta controllare l'LSB, e per il resto si utilizzano tutti gli altri bit allo scopo.

Altro vantaggio, il puntatore nullo, che viene usato internamente quando si indica una condizione d'errore, coincide esattamente col puntatore a un oggetto generico, che ha tutti i bit di "non tag" a zero.

Ovviamente avendo 4 bit per i tag, sarebbe ancora meglio, perché sarebbe possibile specificare 8 tipi oggetto diversi.

Il problema, come dicevo, è che ci sarebbe da stravolgere l'intera virtuale machine di CPython, che usa "allegramente" puntatori a PyObject ovunque.

Un lavoraccio, insomma, ed è la cosa che fa desistere al momento, a fronte di possibili vantaggi.

Forse per un progetto del genere ci si dovrebbe rivolgere a PyPy, in modo da generare automaticamente una macchina virtuale che tenga conto di tutto ciò, lasciando al generatore di VM il compito di smazzarsi tutto quel lavoro.
Continuo a non capire. Prendi un set, per esempio (da wikipedia, voce "Turbo Pascal"):

var
Set1 : set of 1..10;
Set2 : set of 'a'..'z';
Set3 : set of Pear..Orange;


Come fai a vederci una mappatura con un registro hardware, per esempio? Inoltre per il set valgono le operazioni insiemistiche, non quelle a bit! Come hai giustamente detto, i set sono un'astrazione, somigliano alle classiche operazioni matematiche, ma perdono ovviamente il contatto con l'hardware e le operazioni a basso livello necessarie per comandarlo.
In realtà operazioni su insiemi e bit field coincidono, scegliendo un'opportuna implementazione dei primi.

Nello specifico, se, ad esempio, definisci
Set2: set of 0..7;
utilizzi un solo byte e puoi accedere liberamente a ognuno degli 8 bit, o anche a più d'uno, sfruttando le classiche operazioni insiemistiche.

Idem se definisci:
Set3 : set of Pear..Orange;
con Pear che è definito come primo elemento dell'enumerativo, e quindi avente sostanzialmente indice pari a 0.

Il discorso è diverso se definisci Set1 come hai fatto prima: partendo con un intero a 1, Turbo Pascal non utilizzerà il primo bit del primo byte, perché in questo caso mappa il valore 1 sul bit 1 e non sul bit 0, per questione di comodità d'implementazione. Questo se non ricordo male. :D Ma dovrebbe essere così.
E' un problema? Direi di no: a ognuno il suo, quindi la parte low level sara' implementata con un linguaggio a basso livello, come il C; poi il resto dell'applicazione sara' fatta con un linguaggio a piu' alto livello. Ma non riesco proprio a vedere come le operazioni di set possano mappare, per esempio, i bit di un registro.
Puoi farlo solo se conosci l'implementazione dei set, e quindi sai mappare opportunamente tutti i bit del registro hardware, come dicevo prima.

E' importante, nel caso del Turbo Pascal, far coincidere il bit 0 col primo elemento dell'insieme. Usando il valore 0 se si sta usando un set su un intervallo di valori interi (es: 0..7, oppure 0..15, oppure 0..31), oppure specificando sempre il primo elemento di un enumerativo.

In queste condizioni sei a posto, e puoi controllare ogni singolo bit di un registro usando tranquillamente la comodissima sintassi per gli insiemi. :)
Esiste un'altra estensione, tipo il Pascal che veniva usato sui Macintosh ai tempi del system 6?
Era l'Object Pascal usato da Apple. Ma non so come si comportava con l'implementazione dei set.

sottovento
25-02-2013, 10:16
Il discorso è diverso se definisci Set1 come hai fatto prima: partendo con un intero a 1, Turbo Pascal non utilizzerà il primo bit del primo byte, perché in questo caso mappa il valore 1 sul bit 1 e non sul bit 0, per questione di comodità d'implementazione. Questo se non ricordo male. :D Ma dovrebbe essere così.

Wow! Estremamente rischioso! Cmq se funziona, almeno limitatamente al compilatore..


Era l'Object Pascal usato da Apple. Ma non so come si comportava con l'implementazione dei set.
L'Object Pascal e' arrivato secoli dopo. Mi riferivo proprio alle api di sistema, quelle che comparivano sulla collana "Inside Macintosh" (che, fra l'altro, devo ancora avere da qualche parte), che venivano descritte in PASCAL

The_ouroboros
25-02-2013, 10:42
interessante utilizzo


def hexToRgb(value):
//convert string to hexadecimal number (base 16)
num = (int(value.lstrip("#"), 16))
//shift 16 bits to the right, and then binary AND to obtain 8 bits representing red
r = ((num >> 16) & 0xFF)
//shift 8 bits to the right, and then binary AND to obtain 8 bits representing green
g = ((num >> 8) & 0xFF)
//simply binary AND to obtain 8 bits representing blue
b = (num & 0xFF)
return (r, g, b)

cdimauro
25-02-2013, 11:03
Wow! Estremamente rischioso! Cmq se funziona, almeno limitatamente al compilatore..
Beh, sì, devi sapere bene dove mettere le mani. Come col C. :stordita:
L'Object Pascal e' arrivato secoli dopo. Mi riferivo proprio alle api di sistema, quelle che comparivano sulla collana "Inside Macintosh" (che, fra l'altro, devo ancora avere da qualche parte), che venivano descritte in PASCAL
Su questo non ti so dire, mi spiace.
interessante utilizzo


def hexToRgb(value):
//convert string to hexadecimal number (base 16)
num = (int(value.lstrip("#"), 16))
//shift 16 bits to the right, and then binary AND to obtain 8 bits representing red
r = ((num >> 16) & 0xFF)
//shift 8 bits to the right, and then binary AND to obtain 8 bits representing green
g = ((num >> 8) & 0xFF)
//simply binary AND to obtain 8 bits representing blue
b = (num & 0xFF)
return (r, g, b)

Già, perché i valori RGB sono impacchettati in un solo intero, per questioni di efficienza (in memoria sono un byte ciascuno).

The_ouroboros
28-02-2013, 13:03
swap senza appoggio (http://en.wikipedia.org/wiki/XOR_swap_algorithm)

cdimauro
28-02-2013, 13:52
Già. Ecco un'altra versione senza variabile d'appoggio:
x, y = y, x
:fiufiu:

clockover
28-02-2013, 13:57
swap senza appoggio (http://en.wikipedia.org/wiki/XOR_swap_algorithm)

Si ma guarda il risultato con ottimizzazione -O3
void swapXor(int * array, int i, int j){
*(array + i) ^= *(array + j);
*(array + j) ^= *(array + i);
*(array + i) ^= *(array + j);
}

void swap(int* array, int i, int j){
int tmp = *(array + i);
*(array+i) = *(array + j);
*(array + j) = tmp;
}

swap:
.LFB21:
.cfi_startproc
movslq %esi, %rsi
movslq %edx, %rdx
leaq (%rdi,%rsi,4), %rcx
leaq (%rdi,%rdx,4), %rax
movl (%rcx), %esi
movl (%rax), %edx
movl %edx, (%rcx)
movl %esi, (%rax)
ret
swapXor:
.LFB20:
.cfi_startproc
movslq %edx, %rdx
movslq %esi, %rsi
leaq (%rdi,%rsi,4), %rax
leaq (%rdi,%rdx,4), %rcx
movl (%rcx), %edx
xorl (%rax), %edx
movl %edx, (%rax)
xorl (%rcx), %edx
movl %edx, (%rcx)
xorl %edx, (%rax)
ret

clockover
28-02-2013, 13:58
Già. Ecco un'altra versione senza variabile d'appoggio:
x, y = y, x
:fiufiu:

Lo fa anche perl :D (x, y) = (y, x);

The_ouroboros
28-02-2013, 14:12
Si ma guarda il risultato con ottimizzazione -O3
void swapXor(int * array, int i, int j){
*(array + i) ^= *(array + j);
*(array + j) ^= *(array + i);
*(array + i) ^= *(array + j);
}

void swap(int* array, int i, int j){
int tmp = *(array + i);
*(array+i) = *(array + j);
*(array + j) = tmp;
}

swap:
.LFB21:
.cfi_startproc
movslq %esi, %rsi
movslq %edx, %rdx
leaq (%rdi,%rsi,4), %rcx
leaq (%rdi,%rdx,4), %rax
movl (%rcx), %esi
movl (%rax), %edx
movl %edx, (%rcx)
movl %esi, (%rax)
ret
swapXor:
.LFB20:
.cfi_startproc
movslq %edx, %rdx
movslq %esi, %rsi
leaq (%rdi,%rsi,4), %rax
leaq (%rdi,%rdx,4), %rcx
movl (%rcx), %edx
xorl (%rax), %edx
movl %edx, (%rax)
xorl (%rcx), %edx
movl %edx, (%rcx)
xorl %edx, (%rax)
ret
Interessante :D