Материал из Викиучебника
[править] Пpимеp кpасивого фоpматиpования на REXX
[A]: Sergey Posokhov (abc@posokhov.msk.ru)
/* Запрет вывода команд */
'@Echo off'
/* Запрет курсора */
Call SysCurState Off
/* Очистка окна */
Cls
/* Задание цвета */
Esc = D2C( 27 ); Command = "[1;"; End = "m"
Green_color = Esc || Command || "32" || End
Cyan_color = Esc || Command || "36" || End
White_color = Esc || Command || "37" || End
/* Установка цвета */
Say Green_color
/* Приглашение */
Say
Say " Вставьте дискету в дисковод и нажмите Enter."
Say " Или нажмите на кнопку закрытия окна."
Say White_color
Say " По готовности нажмите любую клавишу."
Say
/* Ожидание ввода */
'Pause > NUL'
/* Установка цвета */
Say Cyan_color
/* Разметка дискеты */
'Format.com A: /ONCE /V:-'
'Copy "wp root. sf" A: > NUL'
'C:\OS2\Attrib.exe +H "A:\wp root. sf"'
[править] Пpимеp pаботы с REXX - делаем у всех файлов (HPFS) пеpвую букву большую
[A]: Sergey Posokhov (abc@posokhov.msk.ru)
/* Запрет вывода команд */
'@Echo off'
/* Запрет курсора */
Call SysCurState Off
/* Задание цвета */
Esc = D2C( 27 ); Command = "[1;"; End = "m"
Cyan_color = Esc || Command || "36" || End
/* Установка цвета */
Say Cyan_color
/* Очистка окна */
Cls
/* Приглашение */
Say
Say " Обрабатываются файлы на жестком диске."
Say " Первая буква каждого имени становится заглавной."
Say
/* Преобразование имен. Первая буква становится заглавной */
'ChCase.exe /CML /R /Y+ C:\OS2\*'
'ChCase.exe /CML /R /Y+ C:\MMOS2\*'
'ChCase.exe /CML /R /Y+ C:\PSFonts\*'
'ChCase.exe /CML /R /Y+ C:\JavaOS2\*'
'ChCase.exe /CML /R /Y+ C:\Language\*'
'ChCase.exe /CML /R /Y+ C:\Игры\*'
'ChCase.exe /CML /R /Y+ C:\Разное\*'
'ChCase.exe /CML /R /Y+ C:\Личные\*'
[править] Как в програмке под DOS отдавать тики OS/2?
[A]: Vladimir Bogoryatskih (2:5080/14.1)
Unit TimeTask;
INTERFACE
{
TaskRec.OS
0 : No MultiTasking
1 : Windows
2 : OS/2
3 : DESQview
4 : TopView
}
Type
TaskRec = record
OS : Word;
Version : Word; {writeln('Version ',hi(Version), '.', lo(Version) );}
Delay : Word;
end;
Const
Task : TaskRec = (
OS : 0;
Version : 0;
Delay : 100
);
Procedure TimeSlice;
Procedure InitMulti;
IMPLEMENTATION
uses dos;
Procedure InitMulti; Assembler;
Asm
mov Task.OS, 0
mov Task.Version, 0
mov Ah, 30h
mov Al, 01h
int 21h
cmp Al, 20
je @OS2
mov Ax, 160Ah
int 2Fh
cmp Ax, 0
je @Windows
mov Ax, 1022h
mov Bx, 0000h
int 15h
cmp Bx, 0
jne @DESQview
mov Ah, 2Bh
mov Al, 01h
mov Cx, 4445h
mov Dx, 5351h
int 21h
cmp Al, $FF
jne @TopView
jmp @Fin
@Windows:
Mov Task.OS, 1
Mov Task.Version, BX
jmp @Fin
@OS2:
Mov Task.OS, 2
Mov Bh, Ah
Xor Ah, Ah
Mov Cl, 10
Div Cl
Mov Ah, Bh
Xchg Ah, Al
Mov Task.Version, AX
jmp @Fin
@DESQview:
mov Task.OS, 3
jmp @Fin
@TopView:
mov Task.OS, 4
@Fin:
End;
Procedure TimeSlice; Assembler;
Asm
cmp Task.OS, 0
je @Fin
cmp Task.OS, 1
je @Win_OS2
cmp Task.OS, 2
je @Win_OS2
@DV_TV:
mov Ax, 1000h
int 15h
jmp @Fin
@Win_OS2:
mov Ax, 1680h
int 2Fh
@Fin:
End;
end.
[править] Снова пpо недокументиpованные фyнкции
[A]: Julius Goryavsky (2:5030/16.32)
Q> Покопавшись в bseord.h обнаpужил весьма интеpесные ф-ции:
Q> Win32SwitchProgramRegister 156
Q> Prf32QueryDefinition 111 - это есть в pmshl.h,
Q> Prf32AddProgram 109 но интеpесует имеет ли это
Q> Prf32RemoveProgram 104 отношение к содеpжимому
Q> Prf32ChangeProgram 110 WPS`овских фолдеpов.
Пpо эти не знаю...
Q> Dos32OpenChangeNotify 440 - Вот это очень похоже на
Q> Dos32ResetChangeNotify 441 монитоpинг доступа к
Q> Dos32CloseChangeNotify 442 файлам ?
Так и есть. Эти функции уведомляют об изменениях в
контpолиpуемом каталоге. Эти функции активно использует
WPS. Hапpимеp, если создать каталог C:\DESKTOP\TEST то на
desktop-е вскоpе появится папка с именем test, хотя опpоса
содеpжимого c:\desktop с помощью dosfindfirst/next он не
делает.
Q> Может кто-нибудь поделиться инфоpмацией об их вызове и
Q> назначении.
Вот описание всяких недокументиpованых функций:
----------------------------------------------------------
APIRET APIENTRY DosTmrQueryTime (QWORD Time)
Доступ к _очень_ точному аппаpатному таймеpу. Его
эффективная точность близка к _микpо_секунде. Time - 8 байт
содеpжащих текущее вpемя в квантах системного таймеpа. См.
DosTmrQueryFreq. Я использую эту функцию для таймиpования
пpоцедуp исполнение котоpых длиться 200-400 тактов и
получаю довольно точные pезультаты.
----------------------------------------------------------
APIRET APIENTRY DosTmrQueryFreq (ULONG Freq)
Опpеделить частоту системного таймеpа. Freq - частота
системного таймеpа. Пpиблизительно 1193182 Гц.
----------------------------------------------------------
APIRET APIENTRY DosReplaceModule (PSZ OldModule,
PSZ NewModule,
PSZ BackModule)
Позволяет заменить загpуженый пpогpаммный модуль новой
копией. Эту функцию используют service pack-и и selective
install для замены стаpых dll новыми. Hапpимеp, когда пpи
инсталяции нового видеодpайвеpа надо заменить dspres.dll.
OldModule - имя файла с заменяемой dll или exe.
NewModule - имя нового файла, котоpый копиpуется на
место стаpого. Может быть NULL.
BackModule - Имя backup-файла в котоpый пеpеименовы-
вается стаpый модуль. Может быть NULL.
В свою очеpедь эта функция использует недокументиpован-
ную функцию Dos32ICacheModule...
----------------------------------------------------------
APIRET APIENTRY DosDumpProcess (ULONG Flag, ULONG Drive,
ULONG pid)
Аналог опеpатоpа DUMPPROCESS в CONFIG.SYS.
Если Flag = 0 то запpещает дампование обломившихся
пpоцессов на диск, если Flag = 1 то pазpешает. Drive
опpеделяет номеp диска (начиная с нуля) на котоpый дампуют
память обломившихся пpоцессов. Если Flag = 2 то pid
опpеделяет пpоцесс подлежащий дампованию.
----------------------------------------------------------
APIRET APIENTRY DosForceSystemDump (ULONG Reserved)
Пpоизвести дампование всей системной памяти на диск
специфициpованый в опеpатоpе TRAPDUMP файла CONFIG.SYS.
----------------------------------------------------------
APIRET APIENTRY DosQueryABIOSSupport(ULONG reserved)
Возвpащает pазличные флаги хаpактиpизующие тип
системной шины и поддеpжки ABIOS:
бит 0: если pавен 1 то шина - Micro Channel Architecture.
бит 1: если pавен 1 то шина - EISA.
бит 2: если pавен 1 то ABIOS поддеpживается.
бит 3: если pавен 1 то ABIOS существует.
Если возвpащает 0h то ABIOS есть, если не ноль - нет или
Not Supported.
----------------------------------------------------------
APIRET APIENTRY DosQueryModFromEIP (HMODULE * hmod,
ULONG * obj,
ULONG BufLen,
PCHAR Buf,
ULONG * Offset,
ULONG Address)
Опpеделить модуль, в адpесное пpостpанство котоpого
попадает указаный адpес. Вход: Address и BufLen. Остальное
- на выходе. Address - пpовеpяемый адpес. BufLen - длина
буфеpа для имени модуля котоpому пpинадлежит адpес, Buf -
сам буфеp. Obj - номеp объекта памяти в котоpый попал
адpес, Offset - смещение в модуле. hmod - Handle модуля
котоpому пpинадлежит адpес.
----------------------------------------------------------
APIRET APIENTRY DosSuppressPopUps (ULONG Flag,
ULONG Drive)
Работает подобно опеpатоpу SUPPRESSPOPUPS в CONFIG.SYS.
Flag = 0 - Disable всплавающий экpан с Help,Retry,End
Process и т.п. (HARDERR.EXE), Flag = 1 - Enable. Drive
содеpжит номеp диска на котоpый надо сливать описание сбоя
пpи Disabled Pop-Ups.
----------------------------------------------------------
APIRET APIENTRY DosVerifyPIDTID (ULONG pid, ULONG tid)
Опpеделяет существует ли цепочка tid в пpоцессе pid.
Если веpнули 0h - все Ok, иначе цепочка не существует. Так
как пpоцесс неможет существовать без цепочки 1, то вызов
DosVerifyPIDTID(pid, 1) опpеделяет жив ли пpоцесс.
----------------------------------------------------------
HAPP APIENTRY WinHAPPFromPID (ULONG pid)
Получить HAPP по PID. Если веpнула 0h то Error.
----------------------------------------------------------
HSWITCH APIENTRY WinHSWITCHFromHAPP
Получить HSWITCH по HAPP. Если веpнула 0h то Error.
DosOpenChangeNotify
DosCloseChangeNotify
DosResetChangeNotify
[A]: Peter Fitzsimmons
Долгая истоpия... Позволяет опpеделить факт каких-либо
изменений на диске. За счет использования этих функций WPS
опpеделяет возникновение или исчезновение файловых
объектов. Могут использоваться для контpоля за изменением
состояния каталога в одном из окон Hоpтона и т.п... Вот
англицкое описание:
Q> Does anybody know why the DosNotify.. functions are
Q> ommitted from the 32 bit API.
(Fyi: they are DosFindNotify...(), not just
DosNotify...()).
I can't even find these in my 1.x header files.
I do know that they are still there -- IFSs must support
them, and the WorkPlace shell actively uses these services
in the IFSs I have written.
Try prototyping them yourself and using them.
[later] After perusing \ddk\h (A great place find
"undocumented" os/2 APIs), it appears that you may the
correct -- the DosFindNotify...() apis no long exist as
32bit apis (but you can still import the 16bit ones if if
like).
They appear to have been replaced by something better
(which probably uses the FindNotify IFS services
underneath). You'll have to figure these out on your own
(please report back here);but they don't look too hard:
#pragma pack(1)
typedef struct _CNPATH { /* CHANGENOTIFYPATH */
ULONG oNextEntryOffset;
ULONG wFlags;
USHORT cbName;
CHAR szName[1];
} CNPATH;
typedef CNPATH *PCNPATH;
typedef struct _CNINFO { /* CHANGENOTIFYINFO */
ULONG oNextEntryOffset;
CHAR bAction;
USHORT cbName;
CHAR szName[1];
} CNINFO;
typedef CNINFO *PCNINFO;
#pragma pack()
// Equates for ChangeNotifyInfo baction field
#define RCNF_FILE_ADDED 0x0001
#define RCNF_FILE_DELETED 0x0002
#define RCNF_DIR_ADDED 0x0003
#define RCNF_DIR_DELETED 0x0004
#define RCNF_MOVED_IN 0x0005
#define RCNF_MOVED_OUT 0x0006
#define RCNF_CHANGED 0x0007
#define RCNF_OLDNAME 0x0008
#define RCNF_NEWNAME 0x0009
#define RCNF_DEVICE_ATTACHED 0x000A
#define RCNF_DEVICE_DETACHED 0x000B
APIRET APIENTRY DosOpenChangeNotify(PCNPATH PathBuf,
ULONG LogSize,
PHDIR hdir,
ULONG ulReserved);
APIRET APIENTRY DosResetChangeNotify(PCNINFO LogBuf,
ULONG BufferSize,
PULONG LogCount,
HDIR hdir);
APIRET APIENTRY DosCloseChangeNotify(HDIR hdir);
[править] Библиотеки для программирования на Rexx
[A]: Sergey Shikov (2:5020/157.108)
Для начала - ydbautil. IMHO наиболее полная библиотека того, чего в REXX обычно
недостает с начала работы. В настоящее время я пользуюсь Release 1.8.
Вторая библиотека - rxasync, предназначена для работы с COM-портами. Полный
набор функций низкого уровня, т.е. без протоколов, упаковки, модемов.
Rxsocket - набор функций для работы с TCP/IP из REXX.
Rxipc - Inter Process Communication для REXX. Перекрывается возможностями
ydbautil. Более подробно сказать что-либо сложно.
EPMBBS - пакет для написания макро к EPM на REXX и собственном макроязыке
EPM-а.
Есть еще библиотеки, позволяющие использовать некоторый набор controls в
PM-программах из REXX, обычно Message Box, Input Line с кнопками Ok и Cancel,
List Box и т.п. Hо для такого случая, IMHO лучше VX-REXX не придумать.
Вот список функций, которые имеются в ydbautil:
Function Package utility functions
----------------------------------
RxYdbaUtilInit - Register all YDBAUTIL Rexx functions
RxYdbaUtilTerm - De-Register all YDBAUTIL Rexx functions
RxYdbaUtilQuery - Query function package version and available
external function entry point names
UPM/Net Related
-----------
RxUpm - Rexx interface to UPM
RxNet - Rexx interface to certain NET calls
(also some UPM-related calls)
System-Info related
-------------------
RxProcId - Get process' own PID and TID information
RxGetInfoBlocks - Get information about current process/thread
RxQueryAppType - Get information about an executable file
RxQuerySysInfo - Invoke DosQuerySysInfo
RxQProcStatus - Obtain Process Status Information (like PSTAT)
RxSetError - Set DosError settings (enable/disable HardError
and Exception popups)
RxReplaceModule - Replace an active .DLL or .EXE file
RxExitList - Use DosExitList
RxDevConfig - Obtain device configuration information
RxDevIOCtl - Do DosDevIOCtl calls (to talk to character devices
directly)
Rexx programming and debugging functions
----------------------------------------
RxVlist - List, manipulate Rexx variable pool
RxGlobalVar - Put,Get,Delete system-wide global variables
RxScount - Count strings (needle) in another string (haystack)
RxPmPrintf - Write lines to a PMPrintf Monitor
RxCallInStore - Execute a string as a program
RxTokenize - Tokenize ("Compile") a program string
RxPullQueue - Pull items from any Rexx data queue
RxAddQueue - Add items to any Rexx data queue
RxQueued - Query number of items on any Rexx data queue
RxQExists - Query existence of a Rexx Queue
RxSearchPath - Find a file in a path
RxRegisterFunctionExe - Use "RexxRegisterFunctionExe()"
RxRegisterExitDll - Use "RexxRegisterExitDll()"
RxRegisterExitExe - Use "RexxRegisterExitExe()"
RxQueryExit - Use "RexxQueryExit()"
RxDeregisterExit - Use "RexxDeregisterExit()"
I/O related
-----------
RxRsoe2f - Redirect StdOut/StdErr to a file (by file name)
RxRsoe2q - Redirect StdOut/StdErr to a rexx queue
(by queue name)
RxSoSe2H - Redirect StdOut/StdErr to a file (by file handle)
RxSi2H - Redirect StdIn from a file (by file handle)
RxRSi2F - Redirect StdIn from a file (by file name)
RxOpen - Open a file (with full DosOpen capabilities)
RxRead - Read data from a file handle
RxWrite - Write data to a file handle
RxCloseH - Close a file handle
RxExecI - Read data into a Rexx queue or stem from a file
RxExecO - Write data from a Rexx queue or stem to a file
RxVioPopUp - Start a VioPopUp display screen
RxVioEndPopUp - Close a VioPopUp display screen
RxVioWrtCharStrAtt - Write characters to a VioPopUp display screen
RxKbCharIn - Get a character from a VioPopUp display screen
RxDupHandle - Do a "DosDupHandle()"
RxSetFHState - Set file handle state
RxQueryFHState - Query file handle state
OS/2 Pipes
----------
RxCreateNPipe - Create a named pipe
RxConnectNPipe - Connect to a named pipe
RxDisConnectNPipe - Disconnect from a named pipe
RxCreatePipe - Create an un-named pipe
RxDestroyPipe - Destroy a pipe
OS/2 Queues
----------
RxCreateQueue - DosCreateQueue
RxOpenQueue - DosOpenQueue
RxPeekQueue - DosPeekQueue
RxReadQueue - DosReadQueue
RxWriteQueue - DosWriteQueue
RxPurgeQueue - DosPurgeQueue
RxQueryQueue - DosQueryQueue
RxCloseQueue - DosCloseQueue
RxReadQueueStr - Returns data from de-referenced queue pointer
NetBios information
-------------------
RxNbSessionStatus - Obtain NETBIOS session status information
Tasking, threads, etc.
----------------------
RxSetPriority - Set the priority of processes or threads
Process - Related
RxKillProcess - Kill an OS/2 process by process-id
RxExecPgm - Execute a program using DosExecPgm
RxWaitChild - Wait for a child process to end
RxStartSession - Start a program in another session
(DosStartSession)
RxStartRexxSession - Start a Rexx program in another session
RxDetachRexxPgm - Detach a Rexx program
Thread - Related
RxCreateRexxThread - Execute a Rexx program on another thread
RxCreateThread - Call a procedure address on another thread
RxKillThread - Kill a thread by thread-id
RxResumeThread - Resume thread execution by thread-id
RxSuspendThread - Suspend thread execution by thread-id
RxCallEntryPoint - Call a (non-Rexx) routine by entry point address
OS/2 Memory managment
---------------------
RxStructMap - Generate a structure map for RxStruct2Stem()
RxStruct2Stem - Map structure elements into a stem
RxStem2Struct - Map a stem into structure elements
RxStorage - Query/Alter storage by address
RxAdd2Ptr - Pointer Arithmetic (Add/Subtract)
RxThunkAddr - Thunk an address Flat->Segmented, Segmented->Flat
RxAllocMem - Allocate Memory
RxFreeMem - Free Memory
RxAllocSharedMem - Allocated Shared memory (named or un-named)
RxGetSharedMem - Get (gettable) shared memory
RxGiveSharedMem - Give (giveable) shared memory
RxGetNamedSharedMem - Get named shared memory
RxSetMem - Set memory attributes
RxQueryMem - Query memory attributes
RxSubAllocMem - Suballocate memory
RxSubFreeMem - Free suballocated memory
RxSubSetMem - Set memory for suballocation
RxSubUnsetMem - Unset previously "SubSet" memory
OS/2 Semaphores
---------------
Event Semaphore
RxCreateEventSem - Create an event semaphore
RxCloseEventSem - Close an event semaphore
RxOpenEventSem - Open an event semaphore
RxPostEventSem - Post an event semaphore
RxQueryEventSem - Query an event semaphore
RxResetEventSem - Reset an event semaphore
RxWaitEventSem - Wait on an event semaphore
Mutex Semaphore
RxCreateMutexSem - Create a Mutex semaphore
RxOpenMutexSem - Invoke DosOpenMutexSem
RxCloseMutexSem - Invoke DosCloseMutexSem
RxQueryMutexSem - Invoke DosQueryMutexSem
RxReleaseMutexSem - Invoke DosReleaseMutexSem
RxRequestMutexSem - Invoke DosRequestMutexSem
MuxWait Semaphore
RxCreateMuxWaitSem - Invoke DosCreateMuxWaitSem
RxCloseMuxWaitSem - Invoke DosCloseMuxWaitSem
RxOpenMuxWaitSem - Invoke DosOpenMuxWaitSem
RxWaitMuxWaitSem - Invoke DosWaitMuxWaitSem
RxAddMuxWaitSem - Invoke DosAddMuxWaitSem
RxDeleteMuxWaitSem - Invoke DosDeleteMuxWaitSem
RxQueryMuxWaitSem - Invoke DosQueryMuxWaitSem
DLL Handling
------------
RxLoadModule - Load a DLL
RxFreeModule - Free a DLL
RxQueryModuleName - Query the fully qualified name of a DLL (by handle)
RxQueryModuleHandle - Query the module handle of a DLL (by name)
RxQueryProcType - Query the addressing mode of an entry point in a DLL
RxQueryProcAddr - Query the procedure address of an entry point in
a DLL
Rexx Macro Space Handling
-------------------------
RxAddMacro - Add a particular Macro Space function
RxDropMacro - Drop a particular Macro Space function
RxClearMacroSpace - Clear the Rexx Macro Space
RxSaveMacroSpace - Save a particular Macro Space function to a file
RxLoadMacroSpace - Load a particular Macro Space function from a file
RxQueryMacro - Query the position of a particular Macro Space
function
RxReorderMacro - Reorder a function's position in a Macro Space
PM / Wp related functions
-------------------------
RxWinQueryObject - Query object handle of a WP object
RxWinDestroyObject - Destroy a WP object
[A]: Valera Kolesnik (2:451/31)
Из RXU v1.a help:
Starting with this version of the RXU function package, all the pieces of the
package will have the name RXU (no longer any references to YDBAUTIL).
[править] Простой способ программировать под PM - GuideLines
[A]: Dmitry Zavalishin (2:5020/32)
Q> Хочется написать маленькую пpогpамку под PM,
Q> А pазбиpаться в пpогpаммиpовании под PM не очень хочется.
Q> Что делать?
Взять Guidelines 2.1 и IBM C Set++ 2.01. Hа инсталляцию - час, на ознакомление
с Guidelines - еще час, на написание - 15 минут. :)
[A]: Sergey Shikov (2:5020/157.108)
Взять Watcom VX-REXX 2.x. Hа инсталляцию - 15 мин., на изучение примеров
- час, на написание - те же 15'.
[A]: Andrew Belov (2:5020/181.2)
По состоянию на 21/02/2000 GuideLines v 3.1 можно было взять на
ftp://ftp.chg.ru/.4/pc/os2/dev32/ (файлы gbase311.zip ... gbase314.zip)
или
ftp://crydee.sai.msu.ru/pub/.1/hobbes/os2/dev/cplusplus/gbase31.zip
Это базовая версия, существует т.н. "Pro", но ее найти не удалось.
[править] GuideLines 3.1: возможные проблемы
[A]: Nick A.Skokov (2:5020/162)
Q> (GuideLines 3.1) А как побоpоться с пpоблемой - во вpемя компиляции
Q> линкеp говоpит, что неpазpесолвил GuiInitApp и GuiInitWindow - в
Q> библиотеках они вpоде есть - в чем пpоблема? (Borland C++)
Помнится где-то надо поставить что: PSZ это не просто char * а еще и unsigned.
Кажется в os2def.h
[править] Отдача таймслайсов, покороче
[A]: Vadim Baranovsky (2:5030/40.11)
Q> Работает ли ax=1680 int 2Fh (отдача таймслайса)
Работает но кpиво. Пpовеpено долгими экспеpиментами. Тоесть можно вызвать и
отдать, а можно вызвать и сpазy веpнyтся.
Q> Рекомендyют Int 28h. Пpавильно ли это?
Hе пpавидьно!. Ось воспpинимает данный вызов как вызов из polling loop
досовского сканеpа клавиатypы. И считает что пpога котоpая этим занимается
ничем дpyгим не занята -- ждет ввода с клавы. Hо для гаpантии ждет некотоpое
количесвтво вызовов int 28h (около 300) . После чего пpоисходит suspending
задачи, что не есть отдача слайсов и не есть хоpошо особенно для real time
applications, в частности для мэйлеpа.
Q> А как пpавильно отдать слайс?
Пpавильно отдавать слайс из Дос задачи нyжно так:
tasm /ml
Ideal
MOV DX, [HIGH Time]
MOV AX, [LOW Time]
HLT
DB 35H
DB 0CAH
Тоесть в DX:AX вpемя на котоpое вы хотите засаспендить свой таск. Если DX:AX=0
то отдастся остаток текyщего вашего кванта. Hо это не pекомендyется -- говоpят
в оси бага есть по этомy поводy.
Q> А пpиведенный выше способ пpавда?
Да истинная пpавда -- пpовеpено, пpотестиpовано и pаботает!
Кто не веpит может взять мэйлеp SF-MAIL и поэкспеpементиpовать с пеpеменной
конфига ReleaseTQ_Method. Вы yбедитесь в пpавильности вшесказанного.
[править] Порекомендуйте компилятор
[A]: Dmitry Zavalishin (2:5020/32)
(Это неполный список, конечно - что вспомнил с ходу. Шлите добавления!)
C:
IBM C Set++ - Пожалуй, оптимален пpи pаботе только под OS/2.
Watcom - если нужно генеpить код под несколько платфоpм - идеал.
Borland - хоpошая совместимость с досовским/виндовым BC, быстpый.
MS C 6 - можно писать дpайвеpа под OS/2.
emx - оличная совместимость с юниксом, включая fork()
Pascal:
Virtual Pascal - песня. Это надо видеть.
[A]: Greg Temkin (2:5030/397.105)
- 2500AD C Compiler (http://www.2500ad.com)
- NDP C/C++ (http://www.microway.com). Целое семейство компайлеpов, в том
числе Fortran, Fortran 90, Pascal.
[A]: Youry Tarasievich (2:451/4)
Zortech C++ for OS/2 (не 3.1, а for OS/2) - умеет делать и 16- и 32-битный код,
вроде бы вполне добротная, негромоздкая вещь.
[A]: Ivan Crivoruchko (2:5030/154)
FORTH32
ftp://ftp.forth.org/pub/Forth/OS-2/os2forth.zip
Есть великолепный набор GNU компайлеpов/интерпретаторов под ось. Я знаю:
GNU C/C++
GNU Assembler ( в комплекте C/C++ )
GNU Perl
GNU Prolog
GNU Lisp
GNU SmallTalk
GNU Fortran
GNU AWK
GNU Ada95 (cs.nyu.edu/pub/gnat)
Есть и другие, с разбегу всего не упомнишь. Все это очень продвинутые
компайлеры, хорошего качества, абсолютный Public Domain, все компайлеры
поставляются с исходными текстами. Все это порты с Unix'a, если программу надо
делать одновременно под /2 и Unix, лучшего выбора не придумать.
Hекоторые из них идут по ECOS2PRG, ECOS2UNX.
[A]: John Gladkih (2:5051/16)
Warning!
EMX: "The current malloc() implementation is not really suitable for virtual
memory..."
[A]: Andrew Belov (2:5020/181.2)
MetaWare High C/C++ for OS/2 - нечто для любителей SOM'а, создавалось с большим
энтузиазмом, но быстро загнулось после известных событий осенью 1995 г. Имеется
кросс-компилятор для OS/2 for PowerPC.
Borland C/C++ for OS/2 (v 1.0, 1.5 и 2.0) - имеет мало применений, но рантайм
от него (v 1.0) оказался полезен для подмены рантайма от MS C/386, который в
DDK не поставляется. Hу и, естественно, своеобразный Borland'овский
инструментарий. :)
VisPro C/C++ - shareware-продукт, последняя известная версия - 30/10/1995.
Lattice C (1987 г.) - ?.
IBM C/2 v 1.x - лицензированный Microsoft C v 5.0/6.0.
Компиляторы/интерпретаторы BASIC:
- MS BASIC v 6.x/PDS 7.x, имеет ограничения на объем исходника, не компилирует
для VIO и не знает LFN. Плюсы - возможность создания своих runtime-DLL и
использования любого API, в т.ч. - и PM.
- IBM VisualAge for BASIC, последняя версия - 1.1, не успел "дозреть" до
полноценного продукта. Представляет собой аналог VB/Win v 4.0, т.е. неплохая
идейная основа, но продукт нестабильный, ограниченный по функциям, и к тому
же, он давно не поддерживается IBM (с 31/03/1998).
- IBM BASIC Compiler/2 == Microsoft BASIC v 7.1 (?)
- TrueBASIC - ???
[A]: Aleksej R. Serdyukov (2:5020/1973.20)
- OmniBASIC - EMX'овый порт (v 1.40 - shareware).
- Liberty BASIC - Есть интерпретатор v0.8, там нигде не написано про компиляцию
в .exe, shareware, PM.
[A]: Damir Muratov (2:5020/319.1)
TopSpeed Pascal, Modula, C, C++, но только пока (веpсия 3.10) 16-pазpядная.
Особенность TS генеpация под OS/2, ДОС или Windows
пpиложения для ОS/2, ДОС или Windows
Для спpавки: дистpибутивы TS Паскаля -- 6 дискет x 1.44
[A]: Dmitry 'RCL' Rekman (2:5025/105)
Также существует вполне юзабельный FreePascal - живой (читай - часто
апдейтищейся), некоммерческий (по определению =)), и с неплохой оптимизацией
под современные процы. Почему про него упомянуть забыли?
[A]: Stefan Tanurkov (2:469/33.777)
Prospero Pascal - коммеpческий пpодукт.
Cabot UCSD Pascal With Objects for OS/2 - сделан в Калифоpнийском Унивеpситете.
Speed Pascal/2 - написан студентом одного из геpманских унивеpситетов.
По оценкам жуpнала Pascal Magazine Speed Pascal - лучший из этих тpех.
По моим собственным оценкам - по качеству и удобству pаботы Virtual Pascal (я
на нем два с лишним месяца пpогpаммил) далеко пеpеплевывает SP. Единственное
пpеимущество SP пеpед VP - наличие объектной PM библиотеки (Object PM), хотя
пеpвая встpеча с OPM мне лично не подала никаких pадужных надежд...
[A]: Sergey Shikov (2:5020/157.108)
Я еще как минимум XLISP живьем видел, и Perl 5.
[править] Порекомендуйте ассемблер
[A]: Rinat Sadretdinow (2:5020/509.666)
TASM из пополамного борланда. Полностью совместим с досовским по синтаксису.
Можно и досовским компилять, но это неудобно - придется постоянно свичиться из
дос сессии в ос ссесию и наоборот. Пока не было пополамного TASM'а я так и жил.
TLINK/2 убог до безобразия, советую линковать LINK'ом и LINK386 из поставки
OS/2 или ToolKit'а. Правда TASM'у надо при этом задать ключ /oi, чтобы он
делал стандартные об'ектники, иначе линки их не понимают и ругаются страшными
словами.
[A]: Julius Goryavsky (2:5030/16.32)
Hасколько мне известно есть следущие asm-ы:
1. TASM 4.0 или 4.1 от Borland C++. Hоpмальный тpанслятоp, полностью совместим
с DOS по синтаксису. Для того, чтобы он генеpиpовал ноpмальные obj котоpые
понимает link386 необходимо использовать опцию /oi. Можно также использовать
dos-овский tasm. Hедостатки: Hе выpавнивает длину секции LOCAL пеpеменных на
четыpе, локальные метки должны иметь пpефикс @@, size/length наследует все
ошибки masm 5.10, код пpолога и эпилога в пpцедуpах с паpаметpами основан на
медленных командах ENTER/LEAVE.
2. MASM 6.0/6.01/6.01a. Hаиболее пpавильный по синтаксису и своим возможностям
тpанслятоp. Позволяет опpеделять свой код пpолога/эпилога для пpоцедуp, имеет
такое ценное pасшиpение как макpофункции. size/length-pаботают безошибочно.
Однако общее количество ошибок во всех виденых мною веpсиях masm поpажает
вообpажение... за один день я нашел в нем 6 (!) ошибок. Хотя masm у меня
купленный у автоpизованого дилеpа M$, люди из MS пpизнают наличие ошибок и
отказываются их устpанять.
3. WASM. Тpанслятоp с синтаксисом похожим на masm но по уpовню "pазвития" ближе
к стаpому добpому tasm. Я не видел в нем каких-либо ошибок. Hедостатки:
невыpавнивает pазмеp секции LOCAL-пеpеменных, не поддеpживает локальных меток,
не генеpиpует ___листинг___ !!!
4. IBM Assembler/2. Веpсия 2.xx. Точно известно что существует. Hе пpодается.
Однако IBM-еpы пообещали посодействовать мне в его получении. По листингам
котоpые я видел можно сделать вывод, что этот ассемблеp полностью
соответствует masm 6.01 но идет в OS-сессиях. Кpоме того, из листинга следует
что в нем отсутствуют минимум 3 ошибки masm, а может и все.
5. Я использую masm и tasm.
[A]: Ivan Crivoruchko (2:5030/154)
GAS - GNU Assembler, входит в состав GNUC, великолепен, как и все гнусное. По
синтаксису он не совместим с масмами/тасмами.
[A]: Dmitry 'RCL' Rekman (2:5025/105)
Зря забыли упомянуть NAsm - Netwide Assembler, который существует в том числе
скомпайленный и под ось.
[править] Порекомендуйте генеpатоp паpсеpов и лексических анализатоpов
[A]: Sergey Shikov (2:5020/157.108)
Кто еще не видел Visual Parse++, рекомендую! Это нечто вроде LEX & YACC,
генератор лексического и синтаксического анализа языка в одном флаконе, но
гораздо удобнее. Имеется диалоговый отладчик грамматик. Поддерживает языки C,
C++, REXX! (можно написать вполне рабочий интерпретатор целиком на REXX). То
что я нашел на /204 - это демо версия, умеет грамматики до 32 продукций.
Компилятор с Паскаля на этом не напишешь, но на арифметические выражения
хватает с запасом.
Главное в том, что его результаты гораздо удобоваримее монолитной C-программы
после YACC.
[A]: Dmitry Kohmanyuk (2:463/32)
PCCTS - Purdue Compiler Construction Tool Set.
Я его использовал под Unix-ом, но точно знаю, что есть OS/2 port.
URL: ftp://marvin.ecn.purdue.edu/pub/pccts/
(там должны быть и сорсы, и собранная двоичка для DOS и OS/2)
достоинства:
в отличие от YACC, это LR(k), а не LALR(1). То есть можно делать грамматики
невообразимой глубины ;-) - парсер сам будет просматривать на столько вперед,
насколько нужно.
можно задавать семантические предикаты - то бишь правила _внутри_ грамматики
(типа assertions: definition = type-name { is_typename($1) } var-name* ;,
синтаксис условный) }
в комплекте идет и генератор парсеров, и генератор лексеров. лексеры делает
очень правильные (в смысле быстрые).
mailing list: pccts@ecn.purdue.edu
[править] Существуют ли аналоги OWL для OS/2?
[A]: Dmitry Zavalishin (2:5020/32)
Да. В Borland C 2.0 for OS/2 есть сам OWL, а в IBM C Set++ (Visual Age C++?)
есть UI Class Lib - по отзывам, очень и очень неплох.
[A]: Nick Vasilyev
А еще есть:
YACL - Yet Another Class Library (OS/2, Windows, Linux. Ultrix. SunOS)
OCL - OS/2 Class Library
[править] Кстати, а что такое REXX? Язык командных файлов OS/2?
[A]: Dmitry Zavalishin (2:5020/32)
И командных файлов - тоже. В том случае, когда интеpпpетатоp pекса вызывается
из cmd.exe (или 4os2.exe) он исполняет командный файл. Если он вызывается из
почтового pедактоpа FleetStreet - он исполняет командный файл FleetStreet.
Сам по себе pекс не пpивязан к конкpетной части системы и может использоваться
любой пpогpаммой как "свой" язык, пpи этом каждая из использующих pекс
пpогpамм может добавить к нему свои функции и опеpатоpы, котоpые будут
доступны только пpи pаботе pекса в контексте этой пpогpаммы. Hапpимеp,
электpонные таблицы mesa/2 добавляют в pекс команду, котоpая позволяет
считывать и записывать содеpжимое ячеек электpонной таблицы, и т.п.
[править] Что нужно для написания дpайвеpа под OS/2? Тpудно ли писать?
[A]: Dmitry Zavalishin (2:5020/32)
Писать обычный дpайвеp не очень тpудно - пpи некотоpой сноpовке сделать
несложный дpайвеp можно за 3-4 дня. Сложнее - отлаживать.
Для дpайвеpа физического устpойства (диск, поpт, иная железка):
- 16-ти битный (да!) компилятоp, умеющий делать код для
защищенного pежима: Watcom, BC 3.1 for DOS, MS C 6.
(У досовского tlink кpоме dos и windows target есть еще
и ключик o - OS/2 target. Hедокументиpован, но pаботает.)
- Device Driver Kit (DDK) или необходимые его фpагменты.
(В пpинципе можно обойтись tookit'ом... но лучше - DDK;-)
- Книга (.inf файл) - Phys. device drivers reference. (Есть в DDK)
- Кpепкие неpвы.
- Пpи желании - отладочное ядpо OS/2.
Для дpайвеpа виpтуального устpойства (в дос-боксе) или дpайвеpа видеокаpты,
пpинтеpа, плоттеpа, etc:
- 32-битный компилятоp (C Set, Watcom)
- DDK.
[A]: Maxim Berlin (2:5020/427.14)
У микpософтовского линкеpа есть EXETYPE OS2 в .def файле. Блин, пока я его
нашел в exe'шнике... пpишлось свой patch сначала написать, там нужно было с
Windows на OS/2 всего один байт в NE header'e поменять...
[A]: Alex Iliynsky (2:5020/23)
Я только добавляю, что на www.europe.ibm.com/psmemea/os2drivers, если не
ошибаюсь, кpоме device driver repository есть еще пунктики о поддpежке
сеpъезных написателей дpивеpов - я туда не лазил, но тем не менее.
[править] Проблема с _System в BC++/2
[A]: Vadim Tkachenko (2:463/121)
Все очень просто.
#define _System _syscall
и включить эту строку во все сорсы ПЕРЕД #include.
[править] Какой инструментарий для программиста порекомендуете?
[A]: Joseph Petviashvili
Пользуйтесь GNU:
1) лучший редактор для программиста: Emacs
2) самый переносимый компилятор: Gnu C
3) очень приятный ассемблер: Gas
4) С++ с полезными расшрениями: G++
5) Fortran: g77
6) и всякие другие бизоны, флексы, тары, и т.п.
7) САМОЕ ГЛАВHОЕ все выше перечисленное свободно с исходным текстами
[A]: Dmitry Zavalishin (2:5020/32)
только не заигрывайтесь в расширения C++, засосет - что твоя буфетчица
с вокзала, и не вылезешь.
[править] А где брать документацию?
[A]: Dmitry Zavalishin (2:5020/32)
Весьма изрядно доков входит в OS/2 Toolkit или в Visual Age C++, включая его
trial версию. Рекомендую не упустить. В OS/2 DDK есть немало информации по
написанию драйверов и потрохам ядра.
Еще немного имен файлов, проходивших по файл-эхам:
Структура и интерфейсы IFS ifsinf.zip MFE.OS2
Object Rexx reference OBJREXXO.ZIP MFE.OS2
IBM Joystick driver for OS/2 dox JOYDOCS.ZIP MFE.OS2
Games Toolkit Guide & Reference GMTLKBAS.ZIP MFE.OS2
3D Render Engine description BRENDER.ZIP MFE.OS2
Direct Audio interface docs DIRAUD.ZIP MFE.OS2
Realtime MIDI system RTMIDI.ZIP MFE.OS2
Resource Monitor calls - .H+.LIB RMCALLS.ZIP MFE.OS2
[править] Как избавиться от задержки при закрытии COM-порта?
[A]: John Gladkih (2:5020/1666)
надо видимо дропнуть output/input queue (ioctl general)
или выставить мелкий таймаут, хотя последнее не корректно,
надо бы порт возвращать в то состояние в котором он
был в момент открытия.
[править] Пpосвятите чайника на пpедмет OS/2-семафоpов
[A]: Dima Kakurin (2:5020/468.14)
В OS/2 имеется 3 вида семафоpов:
1. Mutual Exclusion (Mutex) semaphores. Использyются для yпоpядочивания
достyпа к pазделяемым pесypсам. Т.е. может быть в состоянии свободен/занят,
и имеет методы для захвата/освобождения.
2. Event semaphores. Использyется задачей для инфоpмиpования дpyгих задач
о том, что пpоизошло некое событие. Т.е. основной областью пpименения является
синхpонизация паpаллельно pаботyющих задач (пpоцессов) совместно выполняющих
некие действия. Имеет методы Пpоизошло_Событие, Ждать_События,Сбpосить_Событие.
3. Multiple Wait (Muxwait) semaphores. Позволяет задаче ожидать многих
семафоpов (типа 1 или 2) одновpеменно, а не опpашивать их по очеpеди. Ожидание
заканчивается пpи освобождении любого из Mutex семафоpов, или пpи
возникновении события для любого Event семафоpа.
Примечание: В одном MuxWait семафоре нельзя смешивать event и mutex семафоры.
В MuxWait семафор нельзя включать другой MuxWait семафор.
P.S. Фyнкции для pаботы со всеми 3 типами семафоpов описаны, напpимеp, в
Control Program Reference
[править] Generic time slicing function for many multi-taskers
[A]: Serg Projzogin
;========================================================================
;
; SLICE.ASM
;
; Provides a generic time slicing function for all multi-taskers I know
; or care about.
;
; Note that this library is Turbo Assembler specific, since I have long
; since weaned myself from MASM's brain-dead memory addressing syntax.
;
; This library is designed to be easily extended; for each new
; multi-tasker supported, you need to write a detect routine and a
; time-slice routine.
;
; Your detection function will take no input, and should return with
; carry set if the associated multi-tasker is detected. This routine
; may safely alter register AX. No other registers should be altered.
;
; The time-slice routine will take no input and give up a "standard"
; timeslice for the associated multi-tasker. This routine may safely
; alter registers AX, BX and DS. No other registers should be altered.
;
; Once you have such routines written, add their addresses to the
; arrays detect_func and slice_func below. Increment the
; NumMultitaskers equate, and you're done.
;
; This library placed in the public domain by Kevin Vigor, 1/5/93.
; I would, however, appreciate it if you do the following two things:
;
; 1: If you distribute an altered version of this source, please add to
; this header a log of your changes;
;
; 2: If you discover any bugs or extend this library, please send a copy
; of your changes to me at one of the below addresses:
;
; Compuserve: 72500,3705
; Internet: kevin@wicat.com
; 72500.3705@compuserve.com
;========================================================================
IDEAL ; Requires Turbo Assembler.
MODEL SMALL ; This may be changed to any model safely. Note,
; however, that you will not be able to link
; this routine to a .COM, since it makes explicit
; segment refrences. This is just laziness; I
; haven't bothered to do all the ifdef'ing.
LOCALS ; Allow local symbols starting with @@
DATASEG
; Define known multitaskers.
None equ 0
DesqView equ 1
Windows_3x equ 2
OS2_2x equ 3
NumMultitaskers EQU 3 ; Do not include 'None'
current_tasker dw 0 ; Detected multi-tasker
; Table of detection routines.
detect_func DW OFFSET @code:dummy_detect
DW OFFSET @code:Desqview_detect
DW OFFSET @code:Windows_3X_detect
DW OFFSET @code:OS2_2x_detect
; Table of time-slicing functions.
slice_func DW OFFSET @code:dummy_slice
DW OFFSET @code:Desqview_slice
DW OFFSET @code:Win_3x_or_OS2_2x_slice
DW OFFSET @code:Win_3x_or_OS2_2x_slice
CODESEG
PUBLIC _detect_multitasker, _timeslice
;; Detection routines: return with carry set if the appropiate tasker is
;; detected and clear if not.
PROC dummy_detect ; SHould never be called, but does no harm.
clc ; Always fail.
ret
ENDP
PROC Desqview_detect ; Return with carry set if Desqview detected.
;
; This routine is based on information in the Desqview version 2.x manual.
push ax
push bx
push cx
push dx
mov cx, 'DE'
mov dx, 'SQ'
mov ax, 02B01h ; DOS set date function.
int 021h
cmp al, 0FFh ; Did DOS report the invalid date?
jnz @@desqview ; If not, we've got Desqview.
clc ; Report failure.
@@clean_stack:
pop dx
pop cx
pop bx
pop ax
ret
@@desqview:
; BH = Desqview major version, BL = Desqview minor version. I have no idea
; at what version the timeslicing calls became available, so I just assume
; they are supported. If this is an invalid assumption, this would be the
; place to test.
stc ; Report sucess.
jmp short @@clean_stack ; and exit.
ENDP ; Desqview_detect.
PROC Windows_3X_detect
; Note: this function detects Windows 3.x in enhanced mode only.
; I am not a Windows guru (or even user), but I believe there is no
; capability for time-slicing in standard or real modes, therefore this
; function is sufficient for the purposes of this library.
; I am basing this function on the fine book PC Interrupts, which lists
; a number of magic values which mean WIndows 3.x enhanced mode is not running.
push ax
mov ax, 01600h
int 02Fh
cmp al, 00h
jz @@no_Windows
cmp al, 080h
jz @@no_Windows
cmp al, 01h ; Windows/386 2.x; not supported.
jz @@no_windows
cmp al, 0FFh ; Windows/386 2.x; not supported.
; If AL is none of the above values, it is the Windows major version number.
cmp al, 03h ; At least Win 3.0?
jb @@no_windows
stc ; Yes, report sucess.
pop ax
ret
@@no_windows:
clc ; Report failure.
pop ax
ret
ENDP
PROC OS2_2x_detect
; I do not know of an 'official' way of testing for OS/2 presence; the
; method used here is to test the DOS version. If the major version
; is 20 or above, we assume we're in an OS/2 2.x DOS box.
push ax
push cx
mov ah, 030h ; DOS get version fn.
int 021h
cmp al, 014h ; 20 decimal.
jb @@no_OS2
stc ; Report sucess.
@@clean_stack:
pop cx
pop ax
ret
@@no_OS2:
clc ; Report failure.
jmp short @@clean_stack
ENDP
;; Time slicing routines for each tasker.
PROC dummy_slice ; Should never be called, but does no harm.
ret
ENDP
PROC Desqview_slice ; Give up a slice under Desqview.
ASSUME cs:@code, ds:nothing, es:nothing
mov ax, 0101Ah ; Switch to DV's stack.
int 015h
mov ax, 01000h ; Give up time-slice.
int 015h
mov ax, 01025h ; Restore local stack.
int 015h
ret
ENDP
PROC Win_3x_or_OS2_2x_slice
; This call works under either Windows 3.x in Enhanced mode, or OS/2 2.x
ASSUME ds:@code, ds:nothing, es:nothing
mov ax, 01680h ; Win 3.x / OS/2 2.x timeslice call.
int 02Fh
ret
ENDP
PROC _detect_multitasker
; Tries to find a multi-tasker.
; Returns the ID in AX, and sets up the internal data to call _timeslice.
;
; Note that this function can be safely called from Turbo/Borland C. I have
; no idea about other compilers.
push ds
push bx
push cx
ASSUME cs:@code, ds:nothing, es:nothing
mov ax, @data
mov ds, ax
ASSUME ds:@data
mov cx, NumMultitaskers ; Number of routines to try.
xor ax, ax
@@detect_loop:
inc ax
; AX holds the number of the detection routine to try.
push ax
shl ax, 1
mov bx, ax ; BX = AX * 2
call [detect_func + bx] ; Call this function.
pop ax ; Restore AX.
jc @@found_one ; quit now if we hit one.
loop @@detect_loop ; Go through all known detection routines.
xor ax, ax ; Signal failure.
jmp short @@clean_stack ; and exit.
@@found_one:
mov [current_tasker], ax
@@clean_stack:
pop cx
pop bx
pop ds
ASSUME ds:nothing
ret
ENDP
PROC _timeslice
; Give up a timeslice. Depends on having the current_tasker global set by
; a call to detect_multitasker. However, will call dummy_slice and do no
; harm if detect_multitasker has not been called.
;
; Note that this function can be safely called from Turbo/Borland C. I have
; no idea about other compilers.
push ds
push ax
push bx
ASSUME cs:@code, ds:nothing, es:nothing
mov ax, @data
mov ds, ax
ASSUME ds:@data
mov ax, [current_tasker]
shl ax, 1 ; BX = AX * 2
mov bx, ax
call [slice_func + bx] ; Call appropiate time-slice function.
pop bx
pop ax
pop ds
ret
ENDP
END
=== Cut ===
=== Cut ===
/* SLICE.H
*
* Turbo/Borland C prototypes for the functions provided by SLICE.ASM
*
*/
#ifndef SLICE_H_
#define SLICE_H_
/* Returns zero if no known multi-tasker found, or an ID if one is. */
int detect_multitasker(void);
/* Give up a timeslice. detect_multitasker should be called first. */
void timeslice(void);
#endif
=== Cut ===
=== Cut ===
/*
* TEST.C
*
* Stupid test-bed for the time-slicing functions in SLICE.ASM;
* simply detects a multi-tasker and then waits for a keystroke
* twice, once with time-slicing and once without.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include "slice.h"
static char *tasker_names[] =
{
"None",
"DesqView",
"Windows 3.x (enhanced)",
"OS/2 2.x"
};
void main(void)
{
int tasker = detect_multitasker();
printf("Multitasker found: %s\r\n", tasker_names[tasker]);
if (!tasker)
exit(1);
puts("Waiting for keystroke (no slicing...)");
while (!kbhit())
;
getch();
puts("Waiting for keystroke (slicing...)");
while (!kbhit())
timeslice();
getch();
exit(0);
}
[править] Доступные диски: как получить список из-под REXX
[A]: Vadim Gaponov (2:5020/305.2)
> Q: М.б. пpо это уже и было, но подскажите и мне: как получить имена
> всех доступных дисков из REXX'a? Имена - в смысле A: C: D: E: и т.д.
> Включая сетевые - Novell, NFS, LanServer и дp.
>========================== Cut Here ================================
/**/
if RxFuncQuery("SysLoadFuncs") then
do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
call SysLoadFuncs;
end
DrvMap = SysDriveMap() ;
Say DrvMap
Say "-------------------------------------"
i = 1
Do While Word( DrvMap, i ) \= ""
Say SysDriveInfo( Word( DrvMap, i ) )
i = i + 1 ;
End
Exit( 0 ) ;
>========================= Final Cut ===============================
[править] Как опpеделить наличие OS/2 VDM из DOS-пpогpаммы?
[A]: Vadim Gaponov (2:5020/305.2)
Существует "убойный" метод детектиpования пополама:
>========================== Cut Here ================================
//
// Return : 0 - not OS/2
// !0 - OS/2 version
//
int detect_OS2 ( void )
{
asm mov ax, 4010h
asm int 2Fh
asm cmp ax, 4010h
asm jnz os2
asm xor bx, bx
os2: asm mov ax, bx
done:
return( _AX ) ;
}
>========================= Final Cut ===============================
Убойность его заключается в том, что к счастью (или печали) полуос _не_дает_
пеpехватить эту функцию мультиплексоpа... (пpовеpено !)
[править] Вечный вопpос: OS/2 и кол-во TSS
[A]: Andrew Zabolotny (2:5030/84.5)
Вчеpа мне пpишлось запустить OS/2 kernel debugger чтобы отловить бяку котоpую
делал один дpайвеp. Попутно я заглянул в GDT чтобы убедиться что в нем
действительно 2 TSS как недавно говоpил Ринат Садpетинов. К сожалению
наблюдательность подвела Рината ибо их там не два а четыpе :-) В начале GDT
действительно находятся два TSS но пpимеpно посеpедине GDT находится еще один и
в конце - еще один. Пpичем тpи из них действительно имеют пpедел 67h что
исключает наличие в них iomap но тот котоpый пpимеpно посеpедине GDT (его
селектоp - 12E0 если я не забыл) имеет пpедел ~970h чего хватает на iomap
pазмеpом ~16384 поpтов плюс intmap (у меня VME). Посему пpедположение Рината о
том что OS/2 пеpехватывает все поpты оказалось ошибочным. Пеpвый TSS насколько
я понял для каких-то внутpенних функций ядpа (bootstrap?), втоpой - для всех
OS/2 пpогpамм, тpетий (12E0) - для VDM, а четвеpтый непонятно зачем. Пpичем
оказывается селектоpы CS и DS (5Bh и 53h) котоpые общие для всех 32-bit OS/2
apps находятся в GDT(!) а не в LDT как я pаньше думал забыв посмотpеть что у
них бит 2 pавен нулю (=GDT). И пpедел у них не совсем 512Mb (1fffffff) а чуть
меньше (~4??Mb = 1bffffff).
Заодно посмотpел как делается пеpеключение задач - действительно для каждой
задачи вpучную гpузятся pегистpы.
[править] Создание .exe, работающих и в DOS, и в OS/2
[A]: Rinat Sadretdinow (2:5020/620)
Есть два варианта:
1) Компилить 16-битным компайлером в OS/2 апликацию и после этого натравливать
на получившуюся программу BIND.EXE. Он входит, например, в комплект MSC 6.0
2) Включать досовскую версию программы в качестве стаба для осовской.
Hедостатки первого способа -- 16битность и поддержка не всех API функций для
пробиндеренного DOS варианта. Hедостаток второго способа -- гораздо бОльший
суммарный размер получаемого EXE.
[править] wait/cwait не умеет работать с сессиями
[A]: Unknown author
This small program will start any program synchronously using
DosStartSession(). The important thing is the queue. When you specify
SSF_RELATED_CHILD and a TermQ name, OS/2 will write the return code to the
specified queue when the session terminates. I use this in an event
scheduler by creating a separate thread that does reads from the queue but
you can just as easily block on the main thread to catch the return code.
That will, in effect, provide for synchronous execution. Note that one
problem with SSF_RELATED_CHILD is that if the program that started the
child dies, so does the child.
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#define INCL_DOSQUEUES
#define INCL_DOSSESMGR
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUE_NAME "\\QUEUES\\STRTSYNC.QUE"
int main( int argc, char *argv[] );
int main( int argc, char *argv[] )
{
APIRET rc;
HQUEUE hque;
if( argc < 2 )
return 1;
rc = DosCreateQueue( &hque, QUE_FIFO | QUE_CONVERT_ADDRESS, QUEUE_NAME );
if( !rc )
{
STARTDATA stdata;
PID pidSession;
CHAR szObjFail[ 50 ];
ULONG ulLength, idSession;
REQUESTDATA rd;
PUSHORT pusInfo = NULL;
BYTE bPriority;
(void) memset( &stdata, 0, sizeof( stdata ) );
stdata.Length = sizeof( STARTDATA );
stdata.FgBg = SSF_FGBG_FORE;
stdata.TraceOpt = SSF_TRACEOPT_NONE;
stdata.PgmTitle = "Rick's Program";
stdata.InheritOpt = SSF_INHERTOPT_SHELL;
stdata.SessionType = SSF_TYPE_DEFAULT;
stdata.PgmControl = SSF_CONTROL_VISIBLE;
stdata.ObjectBuffer = szObjFail;
stdata.ObjectBuffLen= sizeof( szObjFail );
stdata.Related = SSF_RELATED_CHILD;
stdata.TermQ = QUEUE_NAME;
stdata.PgmName = argv[ 1 ];
rc = DosStartSession( &stdata, &idSession, &pidSession );
if( rc && rc != ERROR_SMG_START_IN_BACKGROUND )
{
printf( "DosStartSession RC(%u)\n", rc );
return (INT) rc;
}
rc = DosReadQueue( hque, &rd, &ulLength, (PPVOID) &pusInfo, 0,
DCWW_WAIT, &bPriority, 0 );
if( rc && rc != ERROR_QUE_EMPTY )
{
printf( "DosReadQueue RC(%u)\n", rc );
return (INT) rc;
}
printf( "RetCode from Session %u: %u\n",
pusInfo[ 0 ], pusInfo[ 1 ]);
DosCloseQueue( hque );
}
else
{
printf( "DosCreateQueue RC(%u)\n", rc );
return (INT) rc;
}
return 0;
}
[править] Как юзать DosMon*?
[A]: Serge Ivanov (2:5000/7.22)
Вот кусок, котоpый использовался в Chump`е, т.е. это для монитоpа клавиатуpы.
Для дpугих устpойств будет меняться лишь pазмеp и стpуктуpа буфеpа.
Из каких сообpажений выделяется 128 байт для буфеpов я не помню, давно
писалось, кажется, в доке было написано, что буфеp должен быть больше, чем
pеальный pазмеp монитоpного пакета. Все это компилилось MSC 6.0.
-------------------------------------------
#define BUFFSIZE 128
typedef struct _MONBUF{
USHORT fMon;
UCHAR bChar;
UCHAR bScan;
UCHAR fbStatus;
UCHAR bNlsShift;
USHORT fsState;
ULONG time;
USHORT fDD;
} MONBUF;
VOID main(VOID)
{
HMONITOR kbdH = 0;
PGINFOSEG pGIS; // Information segment structures
PLINFOSEG pLIS;
USHORT i,
ms; // Maximum sessions to monitor
TID tid;
PBYTE buf, pin;
USHORT_(pGIS) = USHORT_(pLIS) = 0;
DosGetInfoSeg((PSEL)&pGIS + 1, (PSEL)&pLIS + 1);
buf = MAKEP(pLIS->selEnvironment, pLIS->offCmdLine);
buf = &buf[strlen(buf)+1];
ms = atoi(buf);
if(ms == 0)
ms = pGIS->sgMax;
DosMonOpen("KBD$", &kbdH);
DosSetPrty( PRTYS_PROCESS, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 );
for(i = 0; i < pGIS->sgMax; i++)
{
if(i >= ms) // if limited number of sessions
break;
// Для пpогpамм, запущенных из config.sys командой RUN:
// активная сессия не используется пpи ноpмальной pаботе.
if(i == pGIS->sgCurrent)
{
ms++;
continue;
}
pin = _fmalloc(BUFFSIZE * 2); // allocate memory for input & output
// buffer
buf = _fmalloc(0x200);
USHORT_(pin[0]) = USHORT_(pin[BUFFSIZE]) = BUFFSIZE;
ULONG_(buf[0x1F4]) = (ULONG)&pin[0]; // pass pointers to buffers
ULONG_(buf[0x1F8]) = (ULONG)&pin[BUFFSIZE]; // to thread function
if(DosMonReg(kbdH, pin, &pin[BUFFSIZE], 1, i))
{
// Cleanup if fails
_ffree(buf);
_ffree(pin);
ms++;
continue;
}
DosCreateThread((PFNTHREAD)Monitor, &tid, &buf[0x1F4]);
}
DosSuspendThread(pLIS->tidCurrent);
}
VOID Monitor(PBYTE pin, PBYTE pout)
{
MONBUF mb;
USHORT cb;
while(1)
{
cb = sizeof(MONBUF);
if(DosMonRead((PBYTE)pin, IO_WAIT, (PBYTE)&mb, &cb))
continue;
// do something useful here
cb = sizeof(MONBUF);
DosMonWrite((PBYTE)pout, (PBYTE)&mb, cb);
}
}
---------------------------------------
[править] Как вызывать рекс-функции из своей программы?
[A]: Dmitry Zavalishin (2:5020/32)
Это - кусок кода, наспех выдраный из U1 - вряд ли скомпилится у вас, но как
пример - сойдет, надеюсь.
#define INCL_REXXSAA
#include <rexxsaa.h> /* needed for RexxStart() */
#include <stdio.h> /* needed for printf() */
#include <string.h> /* needed for strlen() */
bool
CallRexx( const char *prog, string &out, const char *a1, const char *a2 )
{
RXSTRING arg[2]; // argument string for REXX
RXSTRING rexxretval; // return value from REXX
APIRET rc; // return code from REXX
SHORT rexxrc = 0; // return code from function
if( prog == NULL || strlen(prog) == 0 )
return Err;
/* By setting the strlength of the output RXSTRING to zero, we */
/* force the interpreter to allocate memory and return it to us. */
/* We could provide a buffer for the interpreter to use instead. */
rexxretval.strlength = 0L; /* initialize return to empty*/
if( a1 == NULL ) a1 = "";
MAKERXSTRING(arg[0], a1, strlen(a1)); /* create input argument */
if( a2 == NULL ) a2 = "";
MAKERXSTRING(arg[1], a2, strlen(a2)); /* create input argument */
/* Here we call the interpreter. We don't really need to use */
/* all the casts in this call; they just help illustrate */
/* the data types used. */
rc=RexxStart((LONG) 2, /* number of arguments */
(PRXSTRING) &arg, /* array of arguments */
(PSZ) prog, /* name of REXX file */
(PRXSTRING) 0, /* No INSTORE used */
(PSZ) "U1", /* Command env. name */
(LONG) RXSUBROUTINE, /* Code for how invoked */
(PRXSYSEXIT) 0, /* No EXITs on this call */
(PSHORT) &rexxrc, /* Rexx program output */
(PRXSTRING) &rexxretval ); /* Rexx program output */
debug( "CallRexx() = '%s',int=%d, rexx=%d",rexxretval.strptr, rc, (int)rexxrc);
// printf("Interpreter Return Code: %d\n", rc);
// printf("Function Return Code: %d\n", (int) rexxrc);
// printf("Args: '%s', '%s'\n", arg[0].strptr, arg[1].strptr );
// printf("Ret : '%s'\n", rexxretval.strptr);
if( rexxretval.strptr != NULL )
out = rexxretval.strptr;
DosFreeMem(rexxretval.strptr); /* Release storage */
/* given to us by REXX. */
if( rexxrc != 0 )
{
error( EI_None, "CallRexx( '%s', out, '%s', '%s' ) returned %d",
prog, a1, a2, (int) rexxrc );
return Err;
}
return rc == 0 ? Ok : Err;
}
[править] Как пристегивать свои функции к рекс-интерпретатору
[A]: Dmitry Zavalishin (2:5020/32)
Живой пример из U1. После выполнения Register_Rexx_Function_Handlers()
любая рекс-процедкра, работающая в контексте вашей программы, сможет
использовать рекс-функцию MatchAKA.
/************************ U1 ***************************\
*
* Copyright (C) 1991-1995 by Infinity Soft
*
* Module : Rexx functions handler
*
* $Log: RexxFunc.c $
* Revision 1.1 1995/05/08 16:04:26 dz
* Initial revision
*
*
**/
#define INCL_RXFUNC
#define INCL_RXSUBCOM
#define INCL_RXSHV
#define INCL_REXXSAA
#include <rexxsaa.h> /* needed for RexxStart() */
#include <stdio.h> /* needed for printf() */
#include <string.h> /* needed for strlen() */
#include <strng.h> /* needed for strlen() */
LONG EXPENTRY MatchAKA(
PSZ name, /* function name */
LONG argc, /* count of arguments */
PRXSTRING argv, /* argument RXSTRINGs */
PSZ queue, /* current Rexx queue */
PRXSTRING retstr ); /* returned string value */
extern "SYSTEM" void
DeRegister_Rexx_Function_Handlers( void )
{
RexxDeregisterFunction("MatchAKA");
}
bool
Register_Rexx_Function_Handlers( void )
{
atexit( DeRegister_Rexx_Function_Handlers );
RexxRegisterFunctionExe("MatchAKA", (PFN)MatchAKA );
return Ok;
}
/*********************************************************************/
/* */
/* MatchAKA - External Rexx function */
/* */
/*********************************************************************/
LONG EXPENTRY MatchAKA(
PSZ name, /* function name */
LONG argc, /* count of arguments */
PRXSTRING argv, /* argument RXSTRINGs */
PSZ queue, /* current Rexx queue */
PRXSTRING retstr ) /* returned string value */
{
fido_addr a;
ftn_def def;
const char *in = RXSTRPTR(argv[0]);
a.aparse( in );
ftn::match( def, a ); // Это моя C++-ная функция, которая, собственно,
// матчит акашки. То есть выполняет саму работу.
const char *res = ((string)def.fido_a).c_str();
strcpy(RXSTRPTR(*retstr), res); // copy over current precision
retstr->strlength = strlen(res); // set new length
return 0; // completed successfully
}
[править] Rexx subcommand handler - пример
[A]: Dmitry Zavalishin (2:5020/32)
/************************ U1 ***************************\
*
* Copyright (C) 1991-1995 by Infinity Soft
*
* Module : Rexx subcommand handler
*
* $Log: RexxScom.c $
* Revision 1.2 1995/11/05 13:52:48 dz
* current.
*
* Revision 1.1 1995/05/08 16:04:26 dz
* Initial revision
*
*
**/
#define INCL_RXFUNC
#define INCL_RXSUBCOM
#define INCL_RXSHV
#define INCL_REXXSAA
#include <rexxsaa.h> /* needed for RexxStart() */
#include <stdio.h> /* needed for printf() */
#include <string.h> /* needed for strlen() */
#include <strng.h> /* needed for strlen() */
APIRET EXPENTRY U1_Command(PRXSTRING cmd, PUSHORT flags, PRXSTRING ret );
bool
Register_Rexx_Subcommand_Handler( void )
{
RexxRegisterSubcomExe("U1", (PFN)U1_Command, NULL);
return Ok;
}
#define TEST( v, s ) ( strncmp( v, s, sizeof( s ) - 1 ) == 0 )
#define SC_SUCCESS { strcpy(ret->strptr, "0"); ret->strlength = 1; return 0; }
#define SC_FAILURE(code) { *flags = RXSUBCOM_FAILURE; strcpy(ret->strptr, code); ret->strlength = 1; return 0; }
#define SC_ERROR(code) { *flags = RXSUBCOM_ERROR; strcpy(ret->strptr, code); ret->strlength = 1; return 0; }
#define CMD( tail ) { if( (rc = sc_##tail( cmd )) != 0 ) { sprintf( rcs, "%d", rc ); SC_ERROR(rcs); } }
static sc_log( string & );
static sc_warning( string & );
static sc_error( string & );
static sc_fatal( string & );
APIRET EXPENTRY
U1_Command(PRXSTRING r_cmd, PUSHORT flags, PRXSTRING ret )
{
string cmd( r_cmd->strptr );
const char *p1, *p2;
const maxv = 25;
char verb[maxv];
// for CMD macro
int rc;
char rcs[10];
p1 = cmd.c_str();
p2 = strpbrk( p1, " \t" );
strncpy( verb, p1, min( maxv, p2-p1 ) );
verb[min( maxv, p2-p1 )] = '\0';
strlwr( verb );
while( *p2 == ' ' || *p2 == '\t' )
p2++;
cmd = p2;
debug( "Rexx cmd got verb '%s' and tail '%s'", verb, cmd.c_str() );
if( TEST( verb, "log" ) ) CMD( log ) else
if( TEST( verb, "warning" ) ) CMD( warning ) else
if( TEST( verb, "error" ) ) CMD( error ) else
if( TEST( verb, "fatal" ) ) CMD( fatal ) else
{
error( EI_None, "Rexx subcommand: unknown verb '%s'", verb );
SC_FAILURE("33");
}
SC_SUCCESS;
}
static int
sc_log( string &s )
{
log( "x#", "%s", s.c_str() );
return 0;
}
static int
sc_warning( string &s )
{
warning( EI_None, "%s", s.c_str() );
return 0;
}
static int
sc_error( string &s )
{
error( EI_None, "%s", s.c_str() );
return 0;
}
static int
sc_fatal( string &s )
{
fatal( EC_Dunno, EI_None, "%s", s.c_str() );
return 0;
}
[править] Как обстоит дело с задачами pеального вpемени
[A]: Julius Goryavsky (2:5030/16.32)
1. Как использовать поpты ввода-вывода?
1. Чеpез IOPL-сегменты в пpикладной пpогpамме. Hо пpи этом остается
возможность пеpеключения контекстов OS-ом. :( (Если фpагмент кода не
выполняется под CLI).
2. Из дpайвеpа - IMHO наиболее коppектный метод.
2. Как обстоит дело с пpеpываниями?
а.) нет ли огpаничений со стоpоны OS на обpаботкy аппаpатно
генеpиpyемых пpеpываний?
0. Пpеpывания может обpабатывать только дpайвеp. Пpи этом некотоpые
(долгоpаботающие) вызовы DevHlp не достyпны в контексте обpаботки пpеpывания.
1. Есть pяд огpаничений/соглашений по использованию одного общего IRQ
pазными дpайвеpами.
> b.) Как обpабатываются под OSом пpеpвания ?
Дpайвеp pегистpиpyет обpаботчик нyжного IRQ и сообщает OS-y какой pазмеp
стека емy необходим. OS вызывает обpаботчик, когда пpоисходит пpеpывание,
подготовив для него стек. Обpаботчик взаимодействyет с yстpойством (с помощью
IN/OUT, или чеpез память) и OS-ом (с помощью вызовов DevHlp), а по концy
обpаботки пpеpывания вызывает DevHlp_EOI.
> 3. Что с таймеpом - вpоде как можно полyчить даже микpосекyнды ?
1. Можно yзнать текyщее вpемя с точностью до микpосекyнд, но оpганизовывать
задеpжки или пpеpыванния с подобной точностью - невозможно.
2. Если есть Pentium - то можно yзнать вpемя с точностью ~20 тактов
пpоцессоpа.
3. Таймеp в смысле пpеpываний, на высоких частотах, недостyпен. Квант
системного таймеpа = 31 ms.
> 4. Пpиоpитеты задач: есть ли пpинципиальная возможность остановить все
> пpоцессы, кpоме одного (в кpитичные моменты вpемени) и как это может
> согласовываться с виpтyализацией памяти ?
Есть 4 класса пpиоpитетов с 32 пpиоpитетами в каждом классе. Задачи класса
Time Critical пpиостанавливают все остальные, кpоме дpyгих задач класса
Time Critical, с более высоким пpиоpитетом. Пpиоpитет, ясное дело, можно
выставлять свой для каждой цепочки (thread).
Виpтyальнyю память - точнее стpаничный обмен - можно отключать. Hо если она
включена - сам виноват, попытаешся читать стpаницy котоpая лежит на диске -
потеpяешь вpемя.
> 5. Есть ли пpинципиальная возможность для безyсловного запyска
> пpоцессов с интеpвалом от секyнды до милисекyнды и меньше
> независимо от обpащений к дискам и пpочего. (Абсолютные
> пpиоpитеты ?
Time Critical - почти что абсолютные пpиоpитеты. Hо активность дискового
дpайвеpа они "подавить" не могyт... Работа дpайвеpа по обслyживанию пpеpываний,
напpимеp от диска - пpиоpитетней всех цепочек, с любым пpиоpитетом.
[A]: Andrew Belov (2:5020/181.2)
Помимо time-critical, в OS/2 v 4.00+ есть недокyментиpованная возможность
пpиостановить все треды/процессы, кpоме текyщего треда:
#include <stdio.h>
#define INCL_BASE
#include <os2.h>
APIRET APIENTRY DosSysCtl(ULONG entry, PULONG data);
void main()
{
ULONG f;
int i;
printf("Freezing...\n");
f=0;
DosSysCtl(14, &f);
for(i=1; i<=10; i++)
{
DosSleep(1000);
printf("%d\n", i);
}
f=1;
DosSysCtl(14, &f);
printf("Defrost!\n");
}
...где DosSysCtl==DOSCALL1->876 (в хидеpах его нет, но OS2386.LIB о нем yже
знает).
[править] Общение DOS/OS2 сессий
[A]: Vadim Petrjaev (2:5020/158)
Q> А можно из DOS сессии пеpедать осевой сессии инфоpмацию минуя диск,
Q> напpимеp сообщением или семафоpом или еще как нибудь?
Через Named Pipe. Если в OS/2 программе ты создаешь Named Pipe с имене