Interpretator poleceń w Delphi.

0

Witam wszystkich użytkowników !
Mój problem przedstawia się następująco :
Wpadłem na ambitny plan napisać własny interpretator kodu -taki jak command.com
Udało mi się po ciężkiej pracy na łańcuchach napisać programik konsolowy ,który wykonuje polecenia z dowolnego pliku o rozszerzeniu SCS (własne , instalowane przez plik reg). Wykonuje on kilka (jak na razie) poleceń -zmiana koloru czcionki (pojedynczych lini ,całego kodu),czyszczenie ekranu,zatrzymywanie (readln-em), sterowanie beeperem systemowym i kilka innych ciekawych funkcji. Problem się pojawił , gdy zacząłem myśleć o poleceniu GOTO -przeskok do wybranego label'a oraz .Jak mógłbym wykonać następujące polecenia : -formatowanie (najprostsze, bez przełączników) -tworzenie i przypisywanie zmiennych (tak jak %username% itp). Problem wielki , wiem ,że w wysokim poziomie raczej nie napiszę formatowania. Chcę jednak jak najdalej omijać assemblera -dla dobra mojego komputera....
P.S:Program nie zawiera biblioteki CRT, wszystkie polecenia odnośnie koloru i czyszczenia zostały napisane "ręcznie"

bez tytułu.jpg

dodanie obrazka do treści posta - @furious programming

0

Może zainteresuj się tym co stworzył @Patryk27, a pisał własny język skryptowy w FPC.

0

@programista97 - może opisz problem jeszcze raz, tym razem sensowniej i dokładniej, bo z Twojego opisu w sumie nic nie wynika... No i nie zapomnij pokazać kodu, który wykonuje do tej pory obsługiwane polecenia;

Bez kodu i sensownego opisu problemu wiele nie będzie można doradzić.

0

no ja mysle zrobic program ktory podaje parametry kompa moze byc pod cmd tylko jak sie za to zabrac ?

0
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,windows,StrUtils;
    var
 MyFile : TextFile;
 MyText : String;
 Input:string;  
 output1,output2:string;
 echo:boolean;
  MS:TMemoryStatus;
  p                 : COORD;
  nChars            : DWORD;
  buf_info          : CONSOLE_SCREEN_BUFFER_INFO;
  console           : Cardinal;
  TextAttr: Byte;
  LastMode: Word;
  procedure color(text,bcgrnd:byte);
  begin
  LastMode := TextAttr;
  TextAttr := (TextAttr and $F0) or (text and $0F);
  SetConsoleTextAttribute(console, TextAttr);
  LastMode := TextAttr;
  TextAttr := (TextAttr and $0F) or ((bcgrnd shl 4) and $F0);
  SetConsoleTextAttribute(console, TextAttr);
  end;
//---------------------inter32- interpretacja tekstu----------------------------
  procedure inter32;
  var
  i,i2,i3:integer;
  stro:string;

  begin
  i:=0;
  i2:=0;
  i3:=0;
  stro:='';
output1:='';
output2:='';//zerowanie

  while (length(input)>i) do
  begin
   I:=I+1;
   if input[i]=#32 then break;  //wykrycie I spacji
    end;
   if input[i]=#32 then i:=i-1;
   while i2<i do begin
   i2:=i2+1;
   stro:=stro+input[i2];//ekstrakcja pierwszego słowa -polecenia
   output1:=ansiuppercase(stro) ;  //główne polecenie
  end;
if input[i+1]=#32 then  i3:=i+2;
  output2:=MidStr(input,i3,length(input)-i3+1) ;//pozostałe znaki
 //                      tu już jest ok !
  end;


  //----------------------------------------------------------------------------
 procedure loadfrom;
 var i4,i5,c3,c4:integer;
 c1,c2:byte;
 s,s2:string;
    label koniec;
 begin
 i4:=0;
  i5:=0;
 if ((ParamCount>=1) and (FileExists(ParamStr(1))=true))
  then
   begin
        AssignFile(MyFile, ParamStr(1));
        Reset(MyFile);

        while not eof(MyFile) do
begin
                    Readln(MyFile, MyText);
//---------------------Wykonywanie poleceń--------------------------------------
                  //  writeln(MyText);
                    input:=MyText;
                     inter32;
//----------------------polecenia-------------------------------------------
 if output1='TEXT' then if echo then  writeln('Text '+output2) else  writeln(output2);
 if output1='STOP' then begin writeln('Press enter to continue !'); readln; end;
 if output1='STOP_M' then  readln;
 if output1='ECHO' then echo:=true;
 if output1='SLEEP' then sleep(strtoint(output2));
 if output1='NOECHO' then echo:=false;
 if output1='EXE' then WinExec(pchar(output2),sw_normal);
 if output1[1]='|' then goto koniec; //komentarz
 if output1='BEEP' then begin
  while length(output2)>i5 do
  begin
   i5:=i5+1;
   if output2[i5]='_' then break;
  end;
  S2:=output2;
   SetLength(s2,i5-1);
   c3:=strtoint(s2);//strtoint(MidStr(s,7,length(output2)-6)) ;
   c4:=strtoint(MidStr(output2,length(s2)+2,length(output2)));
   if echo then writeln('Beep '+inttostr(c3)+'_'+inttostr(c4));
   windows.beep(c3,c4);
   i5:=0;
   c3:=0;
   c4:=0;
  end;

 if output1='CLEAR' then begin
  p.X := 0;
  p.Y := 0;
  GetConsoleScreenBufferInfo(Console, buf_info);
  FillConsoleOutputCharacter(Console, ' ', buf_info.dwSize.X * buf_info.dwSize.Y, p, nChars);
  GetConsoleScreenBufferInfo(Console, buf_info);
  FillConsoleOutputAttribute(Console, buf_info.wAttributes, buf_info.dwSize.X * buf_info.dwSize.Y, p, nChars);
  SetConsoleCursorPosition(Console, P);
  end;
  if output1='TESTM' then
  begin
  MS.dwLength:=sizeof(ms);
  GlobalMemoryStatus(ms);
   writeln('Used memory : '+inttostr(ms.dwMemoryLoad)+' %');
   writeln('Total Physical Memory : '+inttostr(ms.dwToTalPhys)+' B');
   writeln('Free Physical Memory : '+inttostr(ms.dwAvailPhys)+' B');
   writeln('Total memory paged : '+inttostr(ms.dwTotalPageFile)+' B');
   writeln('Free memory paged : '+inttostr(ms.dwAvailPageFile)+' B');
   writeln('Total virtual memory: '+inttostr(ms.dwTotalVirtual)+' B');
   writeln('Free virtual memory:'+inttostr(ms.dwAvailVirtual)+' B');
  end;
  if output1='COLOR' then begin
  while length(output2)>i4 do
  begin
   i4:=i4+1;
   if output2[i4]='_' then break;
  end;
  S:=output2;
   SetLength(s,i4-1);
   c1:=strtoint(s);//strtoint(MidStr(s,7,length(output2)-6)) ;
   c2:=strtoint(MidStr(output2,length(s)+2,length(output2)));
   if echo then writeln('Color '+inttostr(c1)+'_'+inttostr(c2));
  if NOT ((c1>=255)and(c2>=255)) then color(c1,c2)else if echo  then writeln('Invalid color value(0...255)');
   i4:=0;
  end;
   end;
   end;
Koniec:
        CloseFile(MyFile);
end;

 begin
   console := GetStdHandle(STD_OUTPUT_HANDLE);
 echo:=true;
loadfrom;

end.

Tak wygląda cały kod. (WIEM, wygląda , jakby ktoś pijany go pisał,ale nie robiłem w nim jeszcze porządku). Problem : jak mogła by wyglądać procedura do formatowania , jak "GOTO" -przeskok do etykiet w kodzie . I jeszcze jedno. Program na bank nie powinien odpalić się w DOS-ie ,więc co mu jest potrzebne ,aby był "samowystarczalny".

0

Najważniejsze to teraz zanim zaczniesz robić cokolwiek dalej, to sformatować kod porządnie (dlaczegoż to ludzie nie chcą usilnie używac http://olesio.eu/jcf - ileż się muszę przypominać z tym linkiem jeszcze? :/) i pozbyć się goto.

0

Zabieram się więc za formatowanie :-) problem tu nie z kodem ,bo wszystko śmiga , tylko z dodaniem kolejnej procedury , co powodowałaby przeskok do etykiety w moim pliku oraz procedury formatującej dysk. Co do GOTO w kodzie -jest on raczej chyba niezbędny ,ze względu na to,że taki program będzie musiał sprawdzić kolejną linijkę ,a w przyszłości -jeśli nie rozpozna polecenia- wyświetli błąd. w ten sposób komentarz zaczynający się "|" nie będzie błędem.

1

Nie, mogę Cię zapewnić, że goto nie jest niezbędne.

0
programista97 napisał(a)

problem tu nie z kodem ,bo wszystko śmiga [...]

Problem jest z kodem, bo co z tego że działa, skoro wygląda tragicznie;

Kod jest stricte proceduralny, do tego kupa zmiennych globalnych, mnóstwo zmiennych lokalnych w procedurach, ogromny główny blok programu z bardzo złymi warunkami, nie posiadającymi nawet obsługi braku spełnienia warunku przez Else, co sprawia, że wszystkie są sprawdzane jeden za drugim, nawet jeśli któryś z nich zostanie spełniony; Poza tym instrukcja umożliwiająca sformatowanie dysku sugeruje, że raczej pracujesz nad malware, a nie nad sensownym narzędziem;

Co do GOTO w kodzie -jest on raczej chyba niezbędny [...]

Instrukcja GoTo istnieje do dziś, bo jest pozostałością jeszcze z programowania strukturalnego; Nie zaleca się jej używania, dlatego że tę instrukcję i etykiety (deklarowane w bloku label) można zastąpić zwykłymi warunkami If lub innymi konstrukcjami; Ani nie wpływają pozytywnie na efektywność działania kodu, ani nie zwiększają jego czytelności - wręcz przeciwnie; Dlatego też śmiało możesz zrezygnować z niej;
____Polecam raczej skasować ten kod i napisać wszystko od nowa, tym razem korzystając z programowania obiektowego i parsowania zawartości pliku jak Pan Bóg przykazał; Jeżeli w jednej linii pliku może być zapisana tylko i wyłacznie jedna instrukcja, to po pierwsze musisz walidować zawartość, aby ewentualnie zareagować na błąd składniowy, po drugie wydziel obsługę takiego polecenia do osobnej metody; A jeżeli w plik z "kodem" nie musi mieć budowy liniowej, to do analizy kodu potrzebny będzie tokenizer, co jest dużo trudniejsze;

Coś mi się wydaje - patrząc na Twój kod i widząc jego jakość - że raczej porywasz się z motyką na Słońce; Nie umiesz jeszcze dobrze programować, a już marzy Ci się interpreter własnych skryptów; Polecam Ci albo zrezygnować póki co z tego projektu, albo najpierw przysiąść solidnie do nauki podstaw Delphi i programowania obiektowego;

PS: commander pisze się przez dwa m.

0

Dzięki, takiego zimnego wiadra mi potrzeba ! Jeśli chodzi o przeznaczenie - to zapewniam ,że nie ma to być aplikacja szkodząca użytkownikowi czy maszynie ,na której ma działać. Wszystko na początku miało iść w kierunku tworzenia własnego systemu operacyjnego -własnych skryptów itp. Co do tworzenia kodu ,fakt -straszny ze mnie bałaganiarz (przez co czasami w pewnym momencie przestaję ogarniać kod ) Nie mniej za wszelką cenę nie mam zamiaru się poddać :-) .Jak tylko poprawię wszystko w kodzie ,dam znać !

0

Wszystko na początku miało iść w kierunku tworzenia własnego systemu operacyjnego -własnych skryptów itp.

Jeszcze bardzo daleko Ci do stworzenia nawet najuboższego systemu operacyjnego; Z resztą do sensownego interpretera własnego języka skryptowego także; Tu potrzebna jest spora wiedza, aby napisać ładny obiektowy kod, w którym jego komponenty będą dobrze ze sobą współpracować; Ale działający kod to nie wszystko - duże znaczenie ma też jego efektywność; W sieci można znaleźć dużo różnych artykułów, opisujących techniki tworzenia optymalnego i wysokowydajnego kodu;

Co do tworzenia kodu ,fakt -straszny ze mnie bałaganiarz (przez co czasami w pewnym momencie przestaję ogarniać kod )

Jeśli już teraz nie ogarniasz swojego kodu, który ma raptem 200 linii (nie liczyłem - strzelam), to wyobraź sobie co by było przy większym projekcie, który składałby się z wielu modułów i posiadałby z 10.000 linii kodu łącznie;

Naucz się dobrze podstaw programowania, bo to jest najważniejsze i bez tego ani rusz; Następnie naucz się pisać przejrzyście, aby kod był krótki, czytelny i optymalny; Potem zajmij się programowaniem obiektowym i tak samo - naucz się pisać dobry obiektowy kod; Jak już to opanujesz, będziesz mógł zabrać się za ten projekt i gwarantuję, że jakość kodu będzie o niebo lepsza.

0

Dzięki, zaczynam więc od początku i mam już teraz wizję jak to powinno działać. Pierwsze koty za płoty -Zastosuję wasze rady. Trochę namieszałem ,za co przepraszam a jednocześnie dziękuję za pomoc !

1 użytkowników online, w tym zalogowanych: 0, gości: 1