Hallo zusammen,
ich benötige einen Parser für .map files von dsp's. Nun wollte ich
fragen, ob es hierfür bereits irgendwelche Bibliotheken gibt bevor ich
damit beginne einen eigenen zu schreiben...
Hat jemand eine Idee?
Formate von map Files sind nicht standardisiert. Falls Du die Chance
erhöhen willst, einen fertigen Parser dafür zu finden, solltest Du
Compiler und DSP-Typ nennen.
Andererseits sind diese Formate in der Regel nicht sehr komplex so das
man relativ schnell mal einen Perl-Script dafür hinschreiben kann.
Ohnehin, ist die Auswertung der Inhalte dann das eigentlich umfangreiche
Problem und nicht das parsen. Falls Du mal erklärst was Du auswerten
willst, hast Du vielleicht Glück und jemand hat sowas schon gemacht.
Danke für deine Antwort,
Es geht um: Pro Audio Development Kit (TMDSPDK6727),
Entwicklungsumgebund ist das Code Composer Studio 3.3.
Ist ein Parser in C / C++ viel aufwändiger als mit Perl?
Danke für deine Antwort,
Pro Audio Development Kit (TMDSPDK6727), Entwicklungsumgebung ist das
Code Composer Studio 3.3.
Ist ein Parser in C / C++ viel aufwändiger als mit Perl?
>Ist ein Parser in C / C++ viel aufwändiger als mit Perl?
Unter der Voraussetzung das ein map-File zu parsen ist, sehe ich Perl im
Vorteil (etwa 80% weniger aufwendig), da wegen der geringen
Kontextsensitivität und der geringen Anzahl von Alternativen und
Verschachtelungsebenen (im Gegensatz zu z.B. der Programmiersprache C)
das meiste mit ein paar regulären Ausdrücken zu erledigen ist.
Da ich meine zwischen den Zeilen zu lesen, das Du den Parser hier im
Vergleich zu der Auswertung der geparsten Daten unterschätzt, noch eine
Bemerkung: Die nötigen Datenstrukturen (Bäume, Hashes etc.) lassen sich
mit Perl schneller verwenden als in purem C. (Andererseits gibt es auch
für C Bibliotheken für solche Sachen). Ich würde für ein map-File
jedenfalls spontan Perl wählen weil mit regulären Ausdrücken so ein
Parser schnell hingeschrieben ist.
Wie üblich gibt es in solchen Fällen kein Schwarz-Weiss. In Perl muss
man sich auch erst einarbeiten. Wenn man C kann, dann ist das sicherlich
nicht ganz so schwierig, aber Perl hat so seine Eigenheiten, die einen
auch ein paar Packungen Kaffee kosten können.
Schreibfehler:
Statt
>Da ich meine zwischen den Zeilen zu lesen, das Du den Parser hier im>Vergleich zu der Auswertung der geparsten Daten unterschätzt ...
muss es heissen
Da ich meine zwischen den Zeilen zu lesen, das Du den Parser hier im
Vergleich zu der Auswertung der geparsten Daten überschätzt ...
Noch eine Ergänzung:
Ich würde für ein map-File jedenfalls spontan Perl wählen weil mit
regulären Ausdrücken so ein Parser schnell hingeschrieben ist. Das
eigentlich aufwendige, die Einordnung der Daten in eine sinnvolle
Struktur (wie die erwähnten Bäume oder Hashes) lässt sich wesentlich
schneller hinschreiben. Ausserdem ist Perl keine streng typisierte
Sprache wie C, so das man in 98% der Fälle Typen einfach ignorieren
kann.
Was für großen Aufwand in der Auswertung der geparsten Daten meinst du
genau?
Also ich benötige von dem map file eigentlich nur die globalen Variablen
geparst (in meinem mapfile sind sie alphabetisch und nach
Speicheradresse sortiert). Zweiteres ist eigentlich sehr praktisch.
Interessant wären dann noch Der Zeitpunkt wann es gelinkt wurde und
Modulname etc..
Also im Prinzip möchte ich einfach die Variablennamen + dazugehörige
Speicheradresse in ein Array parsen, alles weitere sollte dann
eigentlich machbar sein, hoff ich doch :)
>Was für großen Aufwand in der Auswertung der geparsten Daten meinst du>genau?
Etwas genaues konnte ich bisher ja nicht meinen, weil mir ja nicht
bekannt war, auf was hin genau Du das map file untersuchen willst.
>Also ich benötige von dem map file eigentlich nur die globalen Variablen>geparst (in meinem mapfile sind sie alphabetisch und nach>Speicheradresse sortiert). Zweiteres ist eigentlich sehr praktisch.>Interessant wären dann noch Der Zeitpunkt wann es gelinkt wurde und>Modulname etc..
Aha.
>Also im Prinzip möchte ich einfach die Variablennamen + dazugehörige>Speicheradresse in ein Array parsen, alles weitere sollte dann>eigentlich machbar sein, hoff ich doch :)
Was ist denn das weitere nun genau? :-)
Kannst Du (zumindest in Grundlagen) Perl? Wenn ja, könnte man sich mal
den Spass machen hier schnell was zu hacken und Du machst den Rest.
Poste dazu mal ein Beispiel eines map file und beschreibe dazu was Du
damit machen willst. Aber das ich (wir) Dir den kompletten Code machen
kann ich nicht zusagen.
>>Was für großen Aufwand in der Auswertung der geparsten Daten meinst du>>genau?>Etwas genaues konnte ich bisher ja nicht meinen, weil mir ja nicht>bekannt war, auf was hin genau Du das map file untersuchen willst.
Irgendwie ist das auch keine Antwort. Ob und wie kompliziert das ist,
hängt natürlich schon davon ab, was Du mit dem Inhalt des Map-Files
machen willst. Klar. Ich wollte eigentlich nur sagen, das in meiner
Vorstellung, das parsen im Vergleich zu den Auswertungen fast simpel
ist, wenn man jedenfalls nicht triviale Auswertungne annimmt.
Willst Du etwa nur die Symbole einlesen, nach Adresse sortieren und
wieder ausgeben, dann ist das sicherlich einfach und bzgl. der
Komplexität etwa mit dem Parsen vergleichbar. Willst Du aber etwa prüfen
ob sich Bereiche überschneiden, oder, Lücken finden oder sowas, dann ist
das schon etwas komplizierter weil diese Informationen oft nicht
explizit im Map-File enthalten sind sondern erst berechnet werden
müssen.
Andererseits werde ich vermutlich nie den Wunsch haben ein Map-File nur
anders zu sortieren. Mein "Vorurteil", das man nur wegen komplizierter
Dinge ein Map-File parst mag hier unzutreffend sein. Jeder empfindet ja
etwas anderes als nötig/unnötig bzw. einfach/kompliziert.
Also ersteinmal danke für dein Engagement, natürlich möchte ich hier von
niemandem verlangen, dass er mir den ganzen Code programmiert ;) ich
suche lediglich nach einer Einstiegshilfe. Ich habe 0 Erfahrung mit
Perl, das ist das Problem...
Also im Prinzip möchte ich einfach die ausgelesenen Globalen Variablen
zur Laufzeit vom DSP System anfordern und in einer Gui darstellen, sowie
dessen Werte ändern können. Die Kommunikation zum DSP steht im Prinzip
schon, muss eventuell nur noch angepasst werden.
Auszug aus mapfile(Also die für mich relevanten Dinge):
************************************************************************
******
blabla Linker PC v8.2.0
************************************************************************
******
>> Linked Mon Aug 09 13:48:37 2011
OUTPUT FILE NAME: <./Debug/bla.out>
ENTRY POINT SYMBOL: 0
GLOBAL SYMBOLS: SORTED BY Symbol Address
address name
-------- ----
00000008 a
10001c00 b
10001c00 c
10001c00 d
10001c00 e
10001c1c f
10001c38 g
10001c54 h
........ ...
>Ich habe 0 Erfahrung mit Perl, das ist das Problem...
Hm. Das ist dann so ein Grenzfall weil es scheinbar doch ein einfacher
Fall von "Auswertung" ist. Na schaun wir mal.
Ich gehe davon aus, das es eigentlich nur darum geht, die Zeilen
00000008 a
10001c00 b
10001c00 c
10001c00 d
...
in eine andere Datei zu extrahieren. Richtig? Das sollte genau
beschrieben werden!
Schaun wir uns mal so eine Zeile an. Da stehen 8-stellige Zeichenfolgen
die sich alle als Hex-Zahlen interpretieren lassen. Ist das korrekt?
Dann eine Folge von drei Leerzeichen. Danach ein einzelnes Zeichen.
Ungewöhnlich nur einstellige Variablennamen zu benutzen. Ist das ein
Fake oder eine echte Datei? Ist der Quellcode in C? Ist wichtig für die
Syntax von Variablennamen. Zeig mal das Gegenbeispiel für Funktionen in
dem Map-File.
Wie soll dann die Ausgabe aussehen? So eine Liste? Oder umgeformt in
z.B. eine C initialisierung für ein Array von Strukturen oder was?
So ein Code zum einlesen der Datei sieht dann etwas so aus.
1
open(MYINPUTFILE, "<xxx.map");
2
while(<MYINPUTFILE>)
3
{
4
my($line) = $_;
5
6
chomp($line);
7
8
if($line =~ /[a-fA-F0-9]+ \w+/) {
9
print $line, "\n";
10
}
11
}
Wenn Du Dir mal Perl installierst (ich empfehle ActivePerl) und den Code
laufen lässt, wirst Du folgendes sehen: Es werden alle Zeilen
ausgedruckt, die eine beiliebige Folge von Hexadezimalziffern, gefolgt
von drei Leerzeichen gefolgt von einer beliebigen Folge von Zeichen die
in Identifieiern erlaubt sind enthalten. "\w" ist eine sogenannte
Zeichenklasse (die hier etwas oversized ist, aber vermutlich nicht
wirklich falsch).
>Würde man in C hauptsächlich scanf() zum parsen verwenden oder?
Für sowas ja. Da Du kein Perl kannst wäre das vermutlich zu empfehlen,
da Du nicht erst noch was neues lernen musst und ja eigentlich nur ein
paar Infos extrahierst ohne da was kompliziertes auszuwerten.
Ein analoges Beispiel zu dem in Perl wäre etwa (ich lasse mal das
Dateigedöns weg):
Der Vergleich der Perl mit der C Lösung zeigt einen der Punkte die in
Perl einfacher zu handhaben sind.
In dem C Beispiel wird vorausgesetzt, das addr und Identifier Datentypen
sind, die gross genug sind, die grösste vorkommende Adresse und den
längsten vorkommenden Variablennamen aufzunehmen. Genau dimensionieren
kann man diese Typen aber streng genommen nur wenn man die
Syntaxdefinition mit den Limits des Mapfiles kennt, was hier für mich
und vermutlich auch für Dich nicht der Fall ist.
In Perl aber braucht man diese Grössen nicht anzugeben, weil die
tatsächliche Speichergrösse während des Programmablaufs angepasst wird.
Deswegen sind so QuickNDirty Scripts besser in Perl zu schreiben während
effiziente (hier speichereffiziente) Programme besser in C (oder einer
anderen strenger typisierten Sprache) geschrieben werden.
Also im Prinzip kann name und adresse jeweils als String ausgelesen
werden. ich will es direkt in einem Array in C++ speichern, bzw. genauer
gesagt als QString, Oberfläche wird mit Qt gemacht.
struct info
{
QString name;
QString adresse;
}
info arrayParsedVariables[anzahl geparster Variablen]
Die Umwandlungen sind dann kein Problem...
Die Variablennamen waren ein fake. Der Quellcode ist in C.
bsp für funktionen:
1002bba0 00000020 : csl_i2cInit.o
(.text:csl_section:i2c)
1002bbc0 00000020 :
csl_mcaspInit.o (.text:csl_section:mcasp)
1002bbe0 00000020 : csl_sysinit.o
(.text:csl_section:sysInit)
1002bc00 00000020 :
csl_uhpiClose.o (.text:csl_section:uhpi)
Also da ich von Perl keine Ahnung habe, bin ich eigentlich eher
abgeneigt, aber wenn es wirklich so geeignet dafür ist, werde ich es mir
wohl mal anschauen.
Direkt mit C++ zu parsen wär eigentlich auch cool, wobei ein Perl skript
sicher auch leicht in Qt einzubetten wäre..
Wie oben zu sehen ist bräuchte ich dann noch die Anzahl geparster
Variablen, aber ich denke das ist dann kein Problem ;)
1002bba0 00000020 : csl_i2cInit.o (.text:csl_section:i2c)
1002bbc0 00000020 : csl_mcaspInit.o (.text:csl_section:mcasp)
1002bbe0 00000020 : csl_sysinit.o (.text:csl_section:sysInit)
1002bc00 00000020 : csl_uhpiClose.o (.text:csl_section:uhpi)
Sorry das layout der Funktionen hat es vorhin zerschossen.. Der Abstand
der Leerzeichen stimmt nicht , aber ist ja egal..
Funktionen werd ich denke ich sowieso nicht benötigen.
Ja. Wenn Du garkein Perl kannst, dann ist die C-Lösung sicher schneller
zu implementieren.
>Also im Prinzip kann name und adresse jeweils als String ausgelesen>werden.
Genau. Die Addresse kannst Du ja, falls Bedarf besteht, später noch in
ein Integer umwandeln.
Du brauch im Grunde folgendes Gerüst.
1. Map-Datei zum lesen öffnen
2. Eine komplette Zeile lesen
3. "Matchen" mit scanf, resp. sscanf oder fscanf. "%s %s"
4. Falls Match, dann strucht alloziieren, mitglieder setzen.
5. Falls kein Match, dann nichts weiter
6. Prüfen auf eof
7. Falls kein eof dann Schritt 2.
8. Falls eof, dann Datei schliessen.
Was Dir vielleicht im Wege gestanden haben könnte ist die Vermutung, das
Du die Syntax der Datei vollständig beschreiben musst, obwohl Du nur
einen Teil der Inhalte tatsächlich brauchst. Das ist aber nicht
notwendig. Sowohl das C-Beispiel als auch das in Perl ignorieren die
uninteressanten Zeilen einfach. Das geht hier, weil eine syntaktische
Einheit immer komplett mit einer Zeile erledigt ist. (Um die Sprache C
zu "parsen" könnte man von dieser Annahme nicht mehr ausgehen).
>Der Abstand der Leerzeichen stimmt nicht , aber ist ja egal..
Ich bin mir nicht sicher ob das notwendig ist, denn Du könntest ja sehr
viel mehr Erfahrung in C und Dateibehandlung haben als erkennbar ist,
aber...
Hier lauert jedenfalls eine Falle. In C, in dem scanf String musst Du
genau die Anzahl der Leerzeichen angeben!
Ein regelrechter Parser in C, der ein oder mehr Leerzeichen matchen
soll, wäre nicht mehr mit (einem einzelnen) scanf zu machen.
(In Perl könntest Du mit den regulären Ausdrücken spezifizieren, das
mindestens ein, sonst aber beliebig viele Leerzeichen oder auch Tabs
folgen).
Vielen Dank für deine Hilfe!
Also ich denke schon das ich es dann in C bzw. C++ parsen werde,...
wie könnte man definieren das beispielsweise erst ab der Stelle
GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name
angefangen werden soll zu parsen?
Ich bin jetzt leider die nächsten zwei stunden offline, werde aber
später nochmal reinschauen, vielen Dank!
>wie könnte man definieren das beispielsweise erst ab der Stelle>GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name>angefangen werden soll zu parsen?
Es kommte in bisschen auf die Umstände an, ob das überhaupt notwendig
ist.
Ich schriebe ja schon in einem meiner Beiträge:
> Sowohl das C-Beispiel als auch das in Perl ignorieren die uninteressanten >
Zeilen einfach.
Wie kommt das? Nun, scanf gibt als Rückgabewert die Anzahl der
"gematchten" Werte. In dem Beispiel sind es zwei. Gibt es nicht zwei
zurück so liegt keine Zeile der beschriebenen Form vor. In dem
Codebeispiel wird sie dann einfach ignoriert.
Wenn also in der map-Datei sonst eine Zeilen existieren, die von dem
scanf-Muster beschrieben werden, dann brauchst Du nichts weiter zu
prüfen.
Wenn aber, sonst noch Zeilen existieren, die von dem scanf-Muster
beschrieben werden, die Dich aber nicht interessieren, dann musst Du
zusätzliche Kriterien finden.
Nehmen wir mal an, dass vor der Zeile
>GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name
Zeilen stehen, die von dem scanf gematcht werden, Dich aber nicht
interessieren. Dann führst Du einfach ein boolsche Variable z.B. namens
BISHER_IGNORIERE_ICH_DAS_MUSTER ein. Beim Programmstart ist die auf TRUE
gesetzt.
Dann schreibst Du eine zusätzliche Prüfung ob die Zeile
>>GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name
auftritt. So
1
if(strcmp(zeile,"GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name"){
2
BISHER_IGNORIERE_ICH_DAS_MUSTER=False;
3
}
und machst die Prüfung auf die interessante Zeile abhängig von dieser
Variablen.
Ansonsten ignorierst Du einfach weiter alle Zeilen.
In zwei Stunden werde ich wahrscheinlich nicht mehr online sein. Aber
ich denke, mit ein wenig Nachdenken wirst Du schon alleine weiter
kommen.
Viel Erfolg.
Da fehlt ein wichtiges "k".
>Wenn also in der map-Datei sonst keine Zeilen existieren, die von dem>scanf-Muster beschrieben werden, dann brauchst Du nichts weiter zu>prüfen.