Komut satırı parse işlemi (ÇÖZÜLDÜ)

Başlatan fatih6761, 09 Şubat 2013, 22:31:31

fatih6761

Hocalarım, C ile ilgili bir sorum olacak. Temel olarak bir komut satırını parse eden fonksiyonu nasıl yazabilirim?
Hazır alınmış olan bir char **argv ile değil. Elimde sadece komut satırına yollanmış string var mesela
run led=1 state=on

Elimde bu string var. Ve bunu parse etmem gerekiyor. Aslında bir "bash" veya "sh" tarzı bir kabuk yazıyormuş gibi düşünelim. Ya da bir multiboot loader gibi.
Yapmam gereken tek şey bu string'i bir struct'a atamak. İlk bakışta çok zor gelmiyor ama bir türlü toparlayamıyorum.
İlk adım olarak şöyle bbir kod yazdım:
typedef struct {
	char name[10];
	char has_val;
	char val[10];
} option;

typedef struct {
	char cmd_name[10];
	int argc;
	option *args;
} command_line;

void get_arg_count(const char *r){
	int t = 0;
	char c, *p = r;
	int is_after_string = 0;
	while(*r){
		c = *p;
		if(c != ' ')){
			is_after_string = 1;
		}

		if((c == ' ') && is_after_string){
			t++;
			is_after_string = 0;
		}

		p++;
	}
}

void parse_command(int argc, const char *r, command_line *cmd){
	char *p = r;
	int bop, enop, bvop, eop, a = 0;

	/*  allocate arguments  */
	cmd->args = (option*)malloc(sizeof(option) * argc);

	bop = p;

	while(*p != ' '){
		p++;
	}

	eop = p;

	memcpy(cmd->cmd_name, (char*)sop, bop - sop);

	while(*p) {

		bop = p;

		while(*p != ' ')	// count until next whitespace
			p++;

		eop = p;
		p = bop;
		anop = p;

		/*  new argument  */
		while(*p != '='){
			anop++;
			p++;
		}

		if(anop == p){
			cmd->args[a]->has_val = 0;
			bvop = anop + 2;
		}
		else{
			cmd->args[a]->has_val = 1;
		}

		memcpy(cmd->args[a]->name, (char*)sop, anop - bop);	// copy arg name

		if(cmd->args[a]->has_val){
			memcpy(cmd->args[a]->val, (char*)bvop, eop - bvop); // copy arg value
		}
		
		a++;
	}

	cmd->argc = a;
}

Burada parse_command fonksiyonuna yolladığım string, parametre olan cmd'ye parse edilmiş olacak. İlk kelime, yani örnekteki "run" kısmı
cmd->cmd_name dizisine atılacak. Toplam parametre sayısı argc'ye, parametreler ise option struct'ı ile args'a atılacak.
option struct'ına parametre atarken ise parametrenin adı option.name'e kopyalanacak. Eğer '=' ile belirtilmiş bir değere sahip ise option.has_val bayrağı set edilecek, parametrenin değeri ise option.val'e kopyalanacak.
Ben bu şekilde düşündüm ama tam oluşturamadım. Daha iyi fikirlere açığım, kendim kullanacağımdan istediğiniz değişikliği yapabilirsiniz.
Şimdiden teşekkür ederim...
Not: kod örneğimde bop = parametre ve parametre adı başlangıcı, eop = parametre ve parametre değeri sonu
enop = parametre adı sonu, bvop = parametrenin '=' ile belirtilen değerin bağlangıcı oluyor.


Sorun çözüldü bellekte stringleri sonlandırarak hallettim.

mufitsozen

en basit olarak standard lib'den strtok(....  kullanilabilir.

http://www.elook.org/programming/c/strtok.html
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Tagli

Ben hiç uğraşmadım ama bildiğim kadarıyla bu işler için hazır yazılmış programlar var. flex ve bison olarak arama yap. Derleyici tasarımı gibi şeyler bu programlarla yapılıyor. Tür olarak da lexer ve parser diye geçiyorlar.
Gökçe Tağlıoğlu

fatih6761

@mufitsozen hocam mesajı yazdıktan sonra aklıma geldi unutmuşum, strtok ile de denedim ama dediğim gibi nedense bir türlü toplayamıyorum. Şöyle hayrına yazabilecek biri varsa sevinirim.
@Tagli hocam flex bison vs. derleyici tasarımında kullanıyor. Bana onun çok ilkel hali lazım. Sadece tek satır bir parse işlemi yapacak. Struct'ları falan değiştirebilirsiniz. Hiç önemli değil ben programa uydururum.

mehmet

#4
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

fatih6761

@mehmet hocam sağolun ama buda işe yaramadı. Dediğiniz gibi parse bölümü var ama hazır bir ifade parse ediliyor. Benimki tek başına string olarak.

fatih6761

@gerbay hocam getopt'u da biliyorum zaten klibc'de de kaynak kodu var ama elimde hazır bir
int argc;
char **argv;

yapısı yok. İş başa düştü, strtok'u bir daha deneyeceğim. Bu kısmı hallettik diyelim, en verimli ve kullanışlı bir şekilde argümanları nasıl bellekte tutmalıyım ? Acaba sabit boyutlu diziler mi daha kolay olur, yoksa dinamik bellek ayırma mı gerekecek?
char argv[ARG_MAX][ARG_MAX];
char *argv[ARG_MAX];
char **argv;

Hangisi MCU'da uygulamak için daha uygundur?

ArifAhmet

Hocam benimde bu konuda sıkıntılarım var. MCU için komut parse ediyorum ve main'den almasını istemiyorum. argc ve argv değişkenleri elle verebilirmiyim? Nasıl yapmalıyım?
Yaşasın Open Source!