Friday, March 30, 2007

Atlante italiano


Se non avete mai visitato il sito di Atlante italiano fatelo ora, prima ancora di continuare a leggere (vi consiglio il link "accesso libero/vecchia versione").
Bello, eh? Tutta (dico tutta) l'Italia vista dall'alto; anche casa vostra, fino ad oggi ignorata da quegli spocchiosi di Google Earth.
Si, perché Google Earth coprirà anche tutta la terra, ma in gran parte lo fa con foto da satellite, il cui livello di dettaglio non é molto soddisfacente. Il sito del ministero dell'ambiente di cui stiamo parlando invece ha la totale copertura del territorio nazionale con foto aeree.
Certo, l'accesso non è dei più comodi: una finestrina piccola in una pagina web, interfaccia obsoleta, necessità di accettare ogni volta i termini di servizio. Come se non bastasse lo script della pagina cerca di impedirvi un normale copia e incolla delle immagini che state vedendo andando a scrivere nella clipboard. Una palese violazione dei vostri diritti fra l'altro; chi ha detto a quesi signori che non abbiate nella clipboard il vostro ultimo romanzo in copia unica?.

Insomma, quanto sarebbe bello poter disporre delle immagini di Atlante Italiano sull'interfaccia di Google Earth. Pensandoci bene però la cosa non è impossibile. Google Earth infatti permette di sviluppare dei moduli esterni grazie ad una interfaccia http/xml, i cosiddetti "network link". Resta però il problema di prendere le immagini da Atlante Italiano. Se ci avete fatto caso prima di cominciare ad utilizzare il sito avete dovuto scaricare ed installare il controllo ActiveX "ECW". Trovato il CLSID dell'oggetto COM e verificato che la DLL relativa contiene una type library è in effetti possibile scrivere un piccolo programma che si comporta da web server per fornire il network link a Google Earth. La spiegazione dei dettagli richiederebbe troppo tempo, ma potete scaricare il programma AiOnGe (Atlante Italiano on Google Earth) e dargli un'occhiata

Thursday, March 29, 2007

Shbang

Se avete scaricato almeno una delle mie utility avrete notato che il sorgente C# comincia sempre con una o piú righe simili a questa:

//!csc %file%

Probabilmente avrete anche intuito che dopo i caratteri //! ci sono le istruzioni per compilare. Quello che non potevate sapere é che ho sviluppato un'utility che applica automaticamente queste istruzioni quando premo F7 da SciTE.
L'utility si chiama shbang, é scritta anch'essa in C# ed analizza appunto le prime righe del file passato come argomento da linea di comando alla ricerca della sequenza iniziale //!. Fintanto che le righe cominciano con questi tre caratteri il seguito viene interpetato come un comando es eseguito. Quando un comando termina con un codice di terminazione diverso da zero l'esecuzione si interrompe. L'output dei comandi viene rimbalzato all'esterno. Ci sono inoltre 3 pseudo variabili:

  • %file%: il nome del file
  • %name%: il nome del file senza estensione
  • %ext%: l'estensione del file

Eventuali righe bianche vengono ignorate, mentre se una riga non inizia con //! l'elaborazione viene interrotta.
In realtá questa non é la sola sequenza di caratteri riconosciuta. Se usate //@ shbang viene chiamato ricorsivamente; il resto della riga viene passato come argomento.

Non dimenticate di specificare command.build.*.c=shbang $(FileNameExt)
nel file di configurazione cpp.properties di SciTE

Perché il nome shbang? Vi risponde Neil Hodgson (proprio lui, l'autore di SciTE) in questo post

Unix and derivatives use a "#!" (hash bang -> shbang) comment on the
first line of a file to specify the default processor of the file so a
Python program often has a first line like:
#! /usr/bin/env python

Wednesday, March 28, 2007

GenAPI


L'ottimo editor SciTE supporta l'autocompletamento tramite file con estensione API.
Ogni riga contiene il prototipo di una funzione del linguaggio in esame o il nome di una proprietà, interfaccia eccetera. Nel sito citato troverete alcuni file API precotti da scaricare per diversi linguaggi come il C (134 righe), C++ con le api di windows (23371 righe). Sarebbe bello averne uno per C# e il problema non é nemmeno cosí difficile da risolvere, per via della reflection, che ci permette di scandagliare le DLL (pardon, assembly) del framework alla ricerca di proprietà metodi interfaccie eccetera. GenAPI fa proprio questo. Da linea di comando potete passargli l'elenco degli assembly da esaminare. Per esempio potete usare un ciclo:
for %f in (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\*.dll) do genapi %f >> genapi.txt
Naturalmente per ottenere il cs.api finale (20743 righe) é meglio passare per sort e uniq per eliminare i duplicati:
sort genapi.txt | sort | uniq > cs.api
Non avete uniq? Scaricate cygwin!

Errlook


È un piccolo strumento distribuito con Visual Studio e con il Platform SDK. Piccolo ma utile: consente di tradurre i codici numerici di errore COM e Windows in una descrizione. A volte però ti tradisce con il deludente "Message not found". Forse non tutti sanno che errlook fa una ricerca nelle cosiddette message table di alcune DLL di distema; nient'altro che risorse dell'eseguibile di un particolare tipo. E che inoltre l'elenco delle DLL da esaminare é configurabile. É però alquanto tedioso inserire uno per uno i moduli che potrebbero contenere una message table. Niente di meglio quindi che scrivere un'utility che lo faccia per noi, modificando opportunamente il registry. Quella che ho scritto io è scritta in C# e si chiama el; la trovate qui.
Deve essere lanciata da linea di comando con un unico argomento: il pattern delle DLL da esaminare:

C:\>el c:\windows\system32\*.dll
C:\windows\system32\activeds.dll
C:\windows\system32\advapi32.dll
C:\windows\system32\appmgmts.dll
C:\windows\system32\appmgr.dll
C:\windows\system32\asferror.dll



Un avvertimento: i moduli aggiunti nel registry possono essere davvero tanti, oltre un centinaio. La cosa naturalmente rallenterà non poco le funzionalità di errlook, soprattutto se avete una macchina lenta

Monday, March 26, 2007

Espressioni regolari come generatori di stringhe

Avete mai pensato di usare le espressioni regolari al contrario?
Voglio dire, non usarle come riconoscitori di stringhe ma come generatori.
Beh, a me la cosa ossessionava da un po' di tempo. La fregatura é che per fare una semplice prova bisogna riscrivere il parser delle espressioni regolari da zero, dato che nessun motore regex che io conosca espone il parser in maniera semplice.
Passata la paura ho usato The Gardens Point Parser Generator, un emulo di YACC per C#, ho rubato una grammatica già fatta da qui, l'ho estesa un po' ed é saltato fuori rexgen.


C:\tmp>rexgen "(a+b*[0-9])+"
abbbbbbb4aaaaabbbbbbbbbb6aaaaaabbb1abbb6aaaabbbbbbbbb6
C:\tmp>



Attualmente supporta concatenamento (ovviamente), raggruppamento ((...)) quantificatori (+,* e ?), range ([...]) positivi e negati ([^...]) ed il metacarattere ., oltre naturalmente all'escaping per i caratteri speciali (()[]\.+*?) e non stampabili (\a\b\f\n\r\t\v).
Il codice é parecchio brutto, ma se lo volete davvero vedere lo trovate qui.
Le ripetizioni indotte dai quantificatori * e + sono arbitrariamente limitate ad un massimo di 10. Specificate semplicemente l'espressione regolare come (unico) parametro della linea di comando, senza dimenticare di usare le virgolette se utilizzate | o degli spazi

Monday, March 19, 2007

SciTE per visualizzare sorgente HTML da Internet Explorer

Per impostare SciTE come editor utilizzato dal comando "View source" di Internet Explorer:


reg ADD "HKLM\SOFTWARE\Microsoft\Internet Explorer\View Source Editor\Editor Name" /ve /t REG_SZ /d "c:\util\sc1.exe"

Tuesday, March 06, 2007

NReLab

In un post precedente ho citato uno strumento di prova di espressioni regolari.
Lo strumento si chiama NReLab e serve appunto per fare esperimenti con le espressioni regolari implementate nel framework .Net.

Esistono parecchi programmi simili. Ognuno ha i suoi vantaggi, cose che gli altri non fanno insomma.
Il mio non fa eccezione.


Expresso
Intuitivo. Ha un designer sicuramente utile per il neofita. Possibilitá di generare codice e salvare su file.



Regular Expression Designer
Essenziale e intuitivo. Manca la possibilitá di salvare e generare codice.



The Regulator
Il piú ambizioso. Plugins,evidenziazione della sintassi, generazione di codice, traduzione in linguaggio naturale. Peccato che sia troppo ambizioso. L'autore evidentemente si é concentrato piú sull'aggiungere nuove funzionalitá che sulla soliditá del tutto. L'interfaccia é tutt'altro che intuitiva. Attivando una nuova opzione l'espressione regolare che avete composto viene cancellata. L'evidenziazione della sintassi spesso é sbagliata. La traduzione in linguaggio naturale mi sembra piú oscura dell'espressione originale. Non fa per me. Molto buona invece é la possiblita di accedere alla libreria di espressioni regolari online.

Quasi tutti hanno inoltre la possibilitá di provare le sostituzioni, cosa assente in NReLab (in effetti non mi sembra una cosa utile).
NReLab ha invece alcune caratteristiche uniche. Non solo puó generare assembly .Net, ma li puó anche aprire in lettura. In sostanza usa gli assembly come formato per salvare le espressioni regolari, con posibilitá quindi di salvarne piú d'una in un solo file. Provate per esempio a caricare System.Web.RegularExpressions.dll (si trova nella cartella dove é installato il framework, ossia C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 o simile). Interessante, no?
Mi sembra anche interessante la colorizzazione dei diversi match (non somiglia a quella della Google Toolbar, é proprio la stessa); cliccando sul testo dei match/group/capture viene sincronizzato l'albero e viceversa.
É possibile generare codice per tutti i linguaggi .Net installati. Infine si possono esportare i risultati in formato XML, cosa che ho utilizzato in quest'altro post.
I sorgenti sono disponibili qui

Monday, March 05, 2007

Tuttocittá

Ho scoperto una cosa curiosa riguardo il sito di Tuttocittá.
Se inviate una query HTTP del tipo

http://www.tuttocitta.it/tcoln/action?msez=500&com=milano&in=via%20solferino&nc=16&_=

(per esempio con curl) riceverete una risposta fatta cosí (ho aggiunto qualche a capo per rendere il tutto piú leggibile):

<code>0</code>
<x>9.187145</x>
<y>
45.4745</y>
<z>
0.6</z>
<zcent>
0.6</zcent>
<fraz></fraz>
<c>
Milano</c>
<com>
Milano (MI)/com>
<prov>
mi</prov>
<topo>
Via Solferino</topo>
<civ>
16</civ>
<cdloc>
51557</cdloc>
<reg>
Lombardia</reg>
<ul></ul>

Insomma, un frammento di XML. Frammento perché non ha un elemento radice. L'origine della cosa é ovviamente l'approccio Ajax della pagina di Tuttocittá.

Bene. Questo si presta ad essere utilizzato in modi interessanti. Se fosse XML e non un frammento tutto sarebbe piú semplice.

Supponiamo per esempio di avere un elenco di indirizzi e volerli geocodificare (recuperare le coordinate geografiche) tutti. E magari avere come risultato un file GPX per poter visualizzare i diversi punti in Google Earth. O ancora inviare i punti al proprio GPS.

Supponiamo inoltre che gli indirizzi siano giá in formato XML. Per esempio così:

<results>
  <match>
    <group id="nome" value="AMANTE CASELLA CENTRO SRL" />
    <group id="indirizzo" value="C.SO MATTEOTTI 61 , TORINO 10121 (TO) 011/540641 " />
    <group id="tipo" value="C.SO" />
    <group id="via" value="MATTEOTTI" />
    <group id="civico" value="61" />
    <group id="citta" value="TORINO" />
    <group id="CAP" value="10121" />
    <group id="prov" value="(TO)" />
    <group id="tel" value="011/540641" />
  </match>
  ...
</results>

(Questo esempio é stato effettivamente prodotto da uno strumento di prova di espressioni regolari con possibilitá di esportare i risultati in XML).

Se l'output di Tuttocittá fosse effettivamente XML potremmo scrivere uno stylesheet XSLT che, facendo leva sulla funcione XPath document() recupera latitudine e longitudine per ogni indirizzo. Cosí non é, ma possiamo scrivere una estensione XSL che ci consenta di trattare opportunamente frammenti XML. Le poche righe di codice C# che seguono servono allo scopo:

using System;
using
System.IO;
using
System.Text;
using
System.Xml;
using
System.Xml.XPath;
using
System.Xml.Xsl;
using
System.Net;
public class DocFrag {
   
public XPathNodeIterator documentFragment(string url) {
       
WebClient wc=new WebClient();
       
string s=wc.DownloadString(url);
       
s="<root>"+s+"</root>";
       
XPathDocument xd=new XPathDocument(new StringReader(s));
       
XPathNavigator xpn=xd.CreateNavigator();
       
return xpn.Select("/");
   
}
}

(Da compilare con il comando "csc -t:library -debug+ -D:DEBUG docfrag.cs")

Con questa ulteriore arma siamo pronti per scrivere lo stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

               xmlns:ext="http://www.docfrag.org">

       <xsl:output indent='yes'/>

 

       <xsl:template match="*"/>

      

       <xsl:template match="/">

               <gpx version="1.1" creator="GPX.XSL"

                               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                               xmlns="http://www.topografix.com/GPX/1/1"

                               xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">

                       <xsl:for-each select="results/match">

                               <xsl:variable name='url'>

                                       <xsl:text>http://www.tuttocitta.it/tcoln/action?msez=500&amp;com=</xsl:text>

                                       <xsl:value-of select="group[@id='citta']/@value"/>

                                       <xsl:text>&amp;in=</xsl:text>

                                       <xsl:value-of select="group[@id='tipo']/@value"/>

                                       <xsl:text>%20</xsl:text>

                                       <xsl:value-of select="group[@id='via']/@value"/>

                                       <xsl:text>&amp;nc=</xsl:text>

                                       <xsl:value-of select="group[@id='civico']/@value"/>

                                       <xsl:text>&amp;_=</xsl:text>

                               </xsl:variable>

 

                               <xsl:variable name='doc' select="ext:documentFragment($url)"/>

 

                               <xsl:choose>

                                       <xsl:when test='$doc/root/x and $doc/root/y'>

                                               <wpt lon='{$doc/root/x}' lat='{$doc/root/y}'>

                                                       <name><xsl:value-of select="group[@id='nome']/@value"/></name>

                                                       <desc><xsl:value-of select="group[@id='indirizzo']/@value"/></desc>

                                               </wpt>

                                       </xsl:when>

                                       <xsl:otherwise>

                                               <xsl:message>Non trovato: <xsl:value-of select="group[@id='indirizzo']/@value"/></xsl:message>

                                       </xsl:otherwise>

                               </xsl:choose>

                       </xsl:for-each>

               </gpx>

       </xsl:template>

</xsl:stylesheet>

Per applicare lo stylesheet utilizzeró l'ottimo nxslt di Oleg Tkachecnko con il comando:

nxslt indirizzi.xml gpx.xsl -af docfrag.dll -ext DocFrag xmlns=http://www.docfrag.org -o p.gpx

...e il gioco é fatto.

del.icio.us tags: , , , ,