XC16 derleme işleminden sonra hangi değişkeni nereye yerleştirdiğini proje_adi.X.production.map diye bir dosyada adrese ve isme göre sıralayarak listeliyor. Dosyada başka bir dolu işime yaramayacak bilgi de var. Ben sadece değişken adresleri ile ilgileniyorum. Şu bölümle örneğin:
External Symbols in Data Memory (by address):
0x0800 __txBufSpace
0x0828 __rxBufSpace
0x0850 _txBuffer
0x085e _rxBuffer
0x086c _state
0x086d _checksum
0x086e _payloadSize
Değişken adlarını bildiğimi varsayalım. Bunların adreslerini bir C programıyla çekmenin en zahmetsiz ve temiz yolu nedir sizce? Yani şöyle bir fonksiyon olmalı:
unsigned int getAddress(FILE* mapFile, char* varName);
Elbette ki GNU/Linux ortamında çalışıyorum. İlk aklıma gelen awk kullanmak oldu, aslında pek bildiğim bir araç değil ama bu işi halletmek için çok derin bir awk bilgisi gerekmiyor sanırım. Kabukta şunu yazmayı denedim (çıktılar da verilmiştir):
$> awk '/state/ {print $1}' proje_adi.X.production.map
0x086c
0x086c
0x086c
Değişken 3 yerde geçtiği için çıktıyı da 3 kez alıyorum. Bunu C'ye fazla uğraşmadan nasıl aktarabilirim? fork-exec ile awk'yı çağırıp çıkışını da kendi programımda bir fd'ye yönlendirirsem (pipe) olur belki ama ne yalan söyleyeyim, üşendim. Daha kolay bir yol var mıdır önerebileceğiniz?
Zaman zaman bu forumda kendimi çok yalnız hissettiğim oluyor. Sorduğum soruların pek kazık olduğunu sanmıyorum ama görülen o ki kimsenin ilgisini çekmiyor.
Neyse, yukarıda bahsettiğim fork-dup2-exec olayını gayet sadeleştiren bir fonksiyon varmış zaten: popen. Görünce adını hatırladım ama hem var olduğunu hem de ne iş yaptığını tamamen unutmuşum. Özetle, bir programı ayrı bir process olarak çalıştırmanıza ve çıktısını da dosya üzerinden okur gibi okumanıza olanak veriyor. Tabi aslında dosya değil pipe üzerinden okuyor.
Örnek kod:
#include <stdio.h>
unsigned int getMemAdr(char* fileName, char* varName);
int main() {
unsigned int adr = getMemAdr("keler.X.production.map", "sysTick");
printf("Address: %#06x\n", adr);
}
unsigned int getMemAdr(char* fileName, char* varName) {
char cmd[150];
sprintf(cmd, "awk \'/%s/ { if (i == 0) { print $1; ++i } }\' %s",
varName, fileName);
FILE* mapFile = popen(cmd, "r");
unsigned int address;
fscanf(mapFile, "%x", &address);
pclose(mapFile);
return address;
}