Deutsch

Командный интерпретатор 22.03.2025

157  
uscheswoi_82 патриот22.03.25 03:15
NEW 22.03.25 03:15 
Последний раз изменено 22.03.25 03:22 (uscheswoi_82)

Всем привет! Делаю командный интерпретатор:

Вот код interp.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE     0
#define FALSE    !TRUE
#define MAX_SUBSTR 10
#define MAX_CMD    15
#define MAX_BUFFER 512

char *cmd[] = {"CON", // 0
        "PRN",// 1
        "F",// 2
        "D",// 3
        "DEL",// 4
        "IF",// 5
        "Q.",// 6
        "MD",// 7
        "CD",// 8
        "FOR",// 9
        "WAIT",// 10
        "REM",// 11
        "VR",// 12
        "VAR",//13
        "BEEP",// 14
        "JMP",//15
               "CL",// 16
        "GXY",// 17
        "RET",// 18
        "ENUM",// 19
        "RUN",// 20
        "DR",// 21
        "ED",// 22
        "MSG",// 23
        "CAL",  // 24
        "none"};  // 25


/* См. https://groups.germany.ru/showmessage.pl?
   Number=41060081&Board=12994140000001 */

char splits[MAX_SUBSTR][250];
int split_str(char *buf, char del, int idx) {
  int j=0, i=0, k=-1;
  for(j=0; j<idx; j++) splits[j][0] = '\0';
    for(j=0; j<strlen(buf); j++) {
      k++;
      splits[ i ][k] = buf[j];
      if(buf[j] == del) {
 splits[ i ][k] = '\0';
 i++;
 k=-1;
      }
   }
   splits[ i ][k+1] = '\0';
   return i;
}


int main(void) {
  char buf[MAX_BUFFER]; // Буфер для команды
  char scr[MAX_BUFFER]; // Буфер для экрана
  FILE *f; // Для файла
  int i = 0; // Для цикла for
  int is_new_line = FALSE; // Перенос строки?
  int is_echo = FALSE; // Эхо?
  int is_file = FALSE; // Читаем из файла?

  f = fopen("STARTUP.INT", "r"); // Открываем файл startup.int
  if(f != NULL) { is_file = TRUE; }
  START:
  while(1) {
    if(is_file == FALSE) {
      printf("\n? ");
      gets(buf);
    }
    else {
      fgets(buf, 512, f);
      if(feof(f)) { fclose(f); is_file = FALSE; goto START; }
    }
    // Если команда Q., то выходим из файла или программы
    if(strcmp(strupr(buf), "Q.") == 0) { 
      if(is_file == FALSE) exit(0);
      else { 
        fclose(f); 
        goto START; 
      }
    }
    // Расщипляем строку на подстроки
    split_str(buf, ' ', MAX_SUBSTR);
    for(i=0; i<MAX_CMD; i++) {
      if(strcmp(strupr(splits[0]), cmd[ i ]) == 0)
        break;
    }

    switch(i) {
    case 0:
      //printf("\nCON");
      // Перенос строки 
      if(strcmp(strupr(splits[1]), "NON") == 0) is_new_line = TRUE;
      else if(strcmp(strupr(splits[1]), "EON") == 0) is_echo = TRUE; // Эхо
      else {
      strncpy(scr, buf+4, strlen(buf)-2);
      printf("%s", scr);
      }
    break;
    default:
      f = fopen(buf, "r"); // Читаем из файла команды
      if(f != NULL) { 
        is_file = TRUE;
        goto START;
      }
      else
      printf("\nНет такого файла или команды.");
    break;
    }
  }
  return 0;
}


Продолжение следует...

Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#1 
uscheswoi_82 патриот22.03.25 05:02
NEW 22.03.25 05:02 
в ответ uscheswoi_82 22.03.25 03:15

Работает вот так:


Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#2 
uscheswoi_82 патриот22.03.25 23:00
NEW 22.03.25 23:00 
в ответ uscheswoi_82 22.03.25 05:02

Короче в моей программе файл startup.int, запускается первый раз, при запуске командного интерпретатора для каких-нибудь настроек, это так-же как в MS-DOS при первом запуске запускались autoexec.bat и config.sys.

Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#3 
uscheswoi_82 патриот24.03.25 03:13
NEW 24.03.25 03:13 
в ответ uscheswoi_82 22.03.25 23:00

Немножко добавил кода:

void convert_wrtime_to_hhmmss(unsigned short wrtime, int *hours, int *minutes, int *seconds) {    
  *hours = (wrtime >> 11) & 0x1F;
  *minutes = (wrtime >> 5) & 0x3F;    
  *seconds = (wrtime & 0x1F) * 2;
}



case 3:
  is_done = _dos_findfirst("*.*",_A_NORMAL,&ffblk);
  while(!is_done) {
    printf("%s", ffblk.name);
    gotoxy(13, wherey());
    printf("%ld", ffblk.size);
    gotoxy(13+9, wherey());
    convert_wrtime_to_hhmmss(ffblk.wr_time, &hours, &minutes, &seconds);
    printf("d:d:d\n", hours, minutes, seconds);
    is_done = _dos_findnext(&ffblk);
  }
break;



Результат работы кода, даём команду d:

? d
BC.BAT      65       02:35:48
INTERP.CPP  3838     01:40:08
INTERP.EXE  17927    03:08:22
INTERP.OBJ  4145     03:08:22
README.DOC  1700     06:11:34
STARTUP.INT 39       02:50:26
TC0000.SWP  262144   03:08:22
TEST.INT    16       01:35:36
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#4 
uscheswoi_82 патриот24.03.25 21:19
24.03.25 21:19 
в ответ uscheswoi_82 24.03.25 03:13

Я немного поменял код, команда теперь называется dr:

char *cmd[] = {"CON", // 0
        "PRN",// 1
        "F",// 2
        "DR", // 3 Теперь DR для отображения файлов и директорий!!!
        "D",// 4
        "DEL",// 5
        "IF",// 6
        "Q.",// 7
        "MD",// 8
        "CD",// 9
        "FOR",// 10
        "WAIT",// 11
        "REM",// 12
        "VR",// 13
        "VAR",//14
        "BEEP",// 15
        "JMP",//16
        "CL",// 17
        "GXY",// 18
        "RET",// 19
        "ENUM",// 20
        "RUN",// 21
        "DR",// 22
        "ED",// 23
        "MSG",// 24
        "CAL",  // 25
        "none"};  // 26



Команда dr:

case 3:
  is_done = _dos_findfirst("*.*",_A_NORMAL,&ffblk);
  while(!is_done) {
    printf("%s", ffblk.name);
    gotoxy(14, wherey());
    printf("%ld", ffblk.size);
    gotoxy(14+9, wherey());
    convert_wrtime_to_hhmmss(ffblk.wr_time, &hours, &minutes, &seconds);
    printf("d:d:d\n", hours, minutes, seconds);
    is_done = _dos_findnext(&ffblk);
  }
break;



Результат работы команды dr:

C:\sanix_2025>bc.bat
Добро пожаловать в SanixOS v1.0
? dr
12345678.123 0        21:14:46
BC.BAT       65       02:35:48
INTERP.CPP   3895     21:15:22
INTERP.EXE   17970    21:15:30
INTERP.OBJ   4215     21:15:30
README.DOC   1700     06:11:34
STARTUP.INT  39       02:50:26
TC0000.SWP   262144   21:15:28
TEST.INT     16       01:35:36
?
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#5 
uscheswoi_82 патриот06.04.25 13:18
NEW 06.04.25 13:18 
в ответ uscheswoi_82 24.03.25 21:19

Продолжаю программировать командный интерпретатор. Улучшил код:

1.

#define OS_VERSION "1.0"
#define FALSE 0
#define TRUE 1



2

int day;
int month;
int year;



3.

char *messages[] = {"Нет такого файла или команды.",
"Версия командного интерпретатора:"};



4.

case 3:
  is_done = _dos_findfirst("*.*",_A_NORMAL,&ffblk);
  while(!is_done) {
    printf("%s", ffblk.name);
    gotoxy(14, wherey());
    printf("%ld", ffblk.size);
    gotoxy(14 + 9, wherey());
    convert_wrtime_to_hhmmss(ffblk.wr_time, &hours, &minutes, &seconds);
    printf("d:d:d", hours, minutes, seconds);
    gotoxy(14 + 9 + 9, wherey());
    convert_wrdate_to_ddmmyyyy(ffblk.wr_date, &day, &month, &year);
    printf("d:d:d\n", day, month, year);
    is_done = _dos_findnext(&ffblk);
  }
break;



5.

case 13:
  // Выдаёт версию командного интерпретатора
  printf("\n%s %s", messages[1], OS_VERSION);
break;



Результат работы программы:

C:\sanix_2025>INTERP.EXE
Добро пожаловать в SanixOS v1.0

? vr
Версия командного интерпретатора: 1.0

? dr
!!           840      01:12:14 25:03:2025
12345678.123 0        22:14:46 24:03:2025
BC.BAT       65       03:35:48 22:03:2025
INTERP.CPP   4624     13:06:58 06:04:2025
INTERP.EXE   18444    13:07:04 06:04:2025
README.DOC   1700     07:11:34 26:02:2004
STARTUP.INT  39       03:50:26 22:03:2025
TEST.INT     16       02:35:36 24:03:2025

?
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#6 
uscheswoi_82 патриот06.04.25 13:20
NEW 06.04.25 13:20 
в ответ uscheswoi_82 06.04.25 13:18

Ой ошибка, вот подправил:

printf("d.d.d\n", day, month, year);



Вот новый результат:

? dr
!!           840      01:12:14 25.03.2025
12345678.123 0        22:14:46 24.03.2025
BC.BAT       65       03:35:48 22.03.2025
INTERP.BAK   4624     13:06:58 06.04.2025
INTERP.CPP   4624     13:18:40 06.04.2025
INTERP.EXE   18444    13:18:44 06.04.2025
INTERP.OBJ   4825     13:18:44 06.04.2025
README.DOC   1700     07:11:34 26.02.2004
STARTUP.INT  39       03:50:26 22.03.2025
TC0000.SWP   262144   13:18:26 06.04.2025
TEST.INT     16       02:35:36 24.03.2025
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#7 
uscheswoi_82 патриот06.04.25 14:04
NEW 06.04.25 14:04 
в ответ uscheswoi_82 06.04.25 13:20, Последний раз изменено 06.04.25 14:06 (uscheswoi_82)

Для тестирования var.cpp:

#include <stdio.h>
#include <string.h>
int var_index=0; // Количество переменных
char var_name[20][10]; // Переменные, максимум до 20 переменных, длина имени переменной макс. 10 символов
char var_value[20][80]; // Значение переменных, максимум до 20 переменных, длина значения макс. 80 символов
// Создаёт переменную в памяти, и добавляет значение в памяти
void add_variable(char *name, char *value) {
  strcpy(var_name[ var_index ], name); // Копирует имя переменной в массив
  strcpy(var_value[ var_index ], value); // Копирует значение в переменной в массив
  // Если переменные меньше 20, то можно добавлять новую переменную
  if(var_index < 20) var_index ++ ;
}
// Ищет и возвращает адрес значения переменной
int get_value(char *name) {
  int i;
  // Ищет переменную name
  for(i=0; i < var_index; i ++) {
    if(strcmp(var_name[ i ], name) == 0) return i;
  }
  return -1; // Ошибка
}
int main(void) {
  int i;
  add_variable("VAR1", "HELLO WORLD"); // Добавляет новую переменную VAR1, и значение HELLO WORLD
  i = get_value("VAR1"); // Ищет переменную VAR1, и возвращает адрес
  if(i != -1) printf("%s", var_value[ i ]); // Если i не -1, то отображает значение переменной по этому адресу, т.е. по i
  return 0;
}



Результат:

C:\sanix_2025>bc VAR.CPP
HELLO WORLD
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#8 
uscheswoi_82 патриотВчера, 00:06
NEW Вчера, 00:06 
в ответ uscheswoi_82 06.04.25 14:04

Дальше доделал, очищает экран, вот код:

#define MAX_CMD    17


case 17:
  // Очищает экран
  clrscr();
break;
Если я кому-то отвечаю, это не значит что я ему симпатизирую, каждый остаётся при своём мнение
#9