;       SCCSID = @(#)inicfg.asm 6.13 92/03/06
page    ,132
Title INICFG.ASM -- CONFIG.SYS parsing routines

SCCSID  equ     "@(#)inicfg.asm 6.13 92/03/06"

;                 IBM/Microsoft Confidential
;
;           Copyright (c) IBM Corporation  1987, 1990
;           Copyright (c) Microsoft Corp.  1987, 1990
;                     All Rights Reserved

; SOURCE FILE NAME:  INICFG.ASM
;
; DESCRIPTIVE NAME:  CONFIG.SYS processor
;
; FUNCTION:      To read and process the CONFIG.SYS file and
;                establish system configuration parameters.
;
; NOTES:
;    DEPENDENCIES  The Token tables must be in the
;                DOSINITDATA group
;    RESTRICTIONS
;
; ENTRY POINTS:  syiConfigParse
;
; EXTERNAL REFERENCES:   SYIOpenFile
;                SYIReadFile
;                SYISaveMessage
;                SYIDisplayMessage
;                SYIPauseOnError
;                SegAlloc
;                SegRealloc
;                SegFree
;                Config_ProcessCommand
;*                                                             *
;* REVISIONS:                                                  *
;*                                                             *
;*   -  001     2/22/91   Mark Rogalski,   IBM                 *
;*      CP20 DCR 1329  Add DOS=UMB  and DEVICEHIGH support     *
;*                                                             *
;*   -  002     4/19/91   Mark Rogalski,   IBM                 *
;*      CP20 DCR 1360  Add DOS=HIGH support                    *
;*                                                             *
;***********************************************************************;BN011;
; 19Jun91 - G.L.Fulk                                                    ;BN011;
; Add support for a DOS ONLY "FILES=" statement in CONFIG.SYS.          ;BN011;
;***********************************************************************;BN011;
; 17Jun92 - Jon Grimm
; DEVICEHIGH=SIZE=xx should support hex values not decimal              ;a25207
; defect a25207                                                         ;a25207
;***********************************************************************;a25207
; 03Nov92 - Allen Wynn
;  Bring Jon's changes (above) into R205 and R206.  Defect 56564
;***********************************************************************78486
; 11Mar94 - Franz Tigges  Feature 78693 put in as defect                78486
;  Allow automatic reboot for Ring 0 traps and IPEs DCR AIPL            78486
;***********************************************************************
; 15Mar96 - Tony Abbondanzio/Joel Smith Feature 148754                  ;148754
;  Interim PNP Solution                                                 ;148754
;******************** End of Specifications ********************

.sall


;include dosseg.inc
;include basemaca.inc
;include osmaca.inc
;include struc.inc
;include fisam.inc
;include inicfg.inc
;include inicmd.inc
;include iniequ.inc
;include initoken.inc
;include mhandle.inc
;include mi.inc
;include basemid.inc
;include pmode.inc
;include sched.inc
;include infoseg.inc
;include inisms.inc
.xlist
include dosseg.inc
include basemaca.inc
include fnoinit.inc
include osmaca.inc
include struc.inc
include fisam.inc
include inicfg.inc
include inicmd.inc
include iniequ.inc
include initoken.inc
include mhandle.inc
include mi.inc
include basemid.inc
include pmode.inc
include sched.inc
include infoseg.inc
include inisms.inc
include advprop.inc                                                     ;BN011;
include inialtf1.inc
.list

        ModName  , FNO_INICFG_ASM
        CpuMode 386

ReferGlobal     SISData,BYTE
ReferGlobal     _SMswapping,BYTE
ReferGlobal     MaxThreads,WORD
ReferGlobal     _twodiskboot,WORD

ReferFlat       _VMProtectedMem,BYTE

ReferGlobal _SMCFGMinFree,dword

extrn           Config_InvalidCommand:near
extrn           Config_ProcessCommand:near
extrn           SYISaveMessage:near
extrn           syiPauseOnError:near
extrn           syiDisplayMessage:near
extrn           syiProcessALTF1File:near

EXTRNFAR        SegAlloc
EXTRNFAR        SegRealloc
EXTRNFAR        SegFree
EXTRNFAR        SYIOpenFile
EXTRNFAR        SYIReadFile
EXTRNFAR        SYICloseFile

ReferInitGlobal CommandTable,BYTE

IF    RAS                                                              ;83839
ReferInitGlobal TrapdumpTable,BYTE                                     ;78486
ENDIF    ; RAS                                                         ;83839

ReferInitGlobal YesNoTable,BYTE
ReferInitGlobal OnOffTable,BYTE
ReferInitGlobal UMBTable,BYTE                    ;BN001
ReferInitGlobal MemManTable,BYTE
ReferInitGlobal AbsDynTable,BYTE
ReferInitGlobal RomTable,BYTE
ReferInitGlobal DevTypeTable,BYTE
ReferInitGlobal syiLowMem,WORD
ReferInitGlobal syiHighMem,WORD
ReferInitGlobal LWTable,BYTE
ReferInitGlobal AltF1Flags,BYTE
ReferInitGlobal AltFxKeyPressed,BYTE
ReferInitGlobal error_messages_displayed,byte

public          Config_VerifyToken                              ;### AC DCR 1520
public          Config_GetChar
public          Config_Sys_Data
public          Config_Sys_File
public          CFG_AutoCheck                                   ;### AC DCR 1520
public          CFG_Break
public          CFG_Dos_Flags                                   ;BN002
public          CFG_Buffers
public          CFG_DiskCache
public          CFG_DiskThresh                                           ;@9312
public          CFG_LazyWrite
public          CFG_FCBCount
public          CFG_FCBKeep
public          CFG_FILESCount                                          ;BN011;
public          CFG_Prompt
public          CFG_PrtBufSize
public          CFG_ProtectOnly
public          CFG_RMSize

if RAS
public          CFG_TraceBuf
public          CFG_TraceBits
public          CFG_LocalTraceBits
endif ;RAS

public          CFG_LocalSubType

public          CFG_Token
public          CFG_LastDrive
public          CFG_ReserveDriveLetter               ;99999
public          CFG_Defaultcache

;****************************************************************************

INITDATA segment
CFG_AutoCheck   db      26 DUP (0)              ;FAT AutoCheck Drives ;### AC DCR 1520
CFG_Break       db      DefaultBreak            ;Break on/off indicator
CFG_Dos_Flags   db      DefaultDosFlags         ;Dos flags for UMB, LOAD HIGH ;BN002
CFG_Buffers     dw      DefaultBuffers          ;Buffers value
CFG_DiskCache   dd      DefaultDiskCache*1024   ;Disk Cache size (bytes)
CFG_DiskThresh  dw      DefaultDiskThresh       ;Disk Cache thresh(sect) ;@9312
CFG_LazyWrite   db      DefaultLazyWrite        ;Lazy Write flag
CFG_FCBCount    dw      DefaultFCBCount         ;FCB count
CFG_FCBKeep     dw      DefaultFCBKeep          ;FCB keep value
CFG_FILESCount  dw      DefaultFILESCount       ;FILES count            ;BN011;
CFG_Prompt      db      DefaultPrompt           ;Prompt on error indicator
CFG_PrtBufSize  dw      DefaultPBUFCount        ;PRN/LPT1 parallel port buf size
                dw      DefaultPBUFCount        ;LPT2 parallel port buf size
                dw      DefaultPBUFCount        ;LPT3 parallel port buf size
CFG_ProtectOnly db      DefaultProtectOnly      ;Protect mode only indicator
CFG_RMSize      dw      DefaultRMSize           ;Real mode box size (bytes)
CFG_LastDrive   db      DefaultLastDrive - 'a'  ;Last drive (A=0)
CFG_ReserveDriveLetter  db      0ffh                    ;99999
CFG_Defaultcache        db      0               ;Default for FAT cache
                        db      0               ;NULL terminate

MSG_Table_No_Config     SMT     <MSG_SYSINIT_AUTO_ALTF1>

MSG_Table_Bad_Config    SMT     <MSG_ITERATED_DATA_EXCEEDS_64K,1>
                SMT_Var <DOSINITDATA:ConfigSysFilename>

MSG_Table_Inval_Cmd     SMT     <MSG_SYSINIT_INVAL_CMD,2>
                SMT_Var <DOSINITDATA:LineStr>
                SMT_Var <DOSINITDATA:CFG_CommandStr>

MSG_Table_Inval_Parm    SMT     <MSG_SYSINIT_INVAL_PARM,3>
                SMT_Var <DOSINITDATA:LineStr>
                SMT_Var <DOSINITDATA:CFG_CommandStr>
                SMT_Var <DOSINITDATA:CFG_Token>

MSG_Table_Missing_Parm  SMT     <MSG_SYSINIT_MISSING_PARM,2>
                SMT_Var <DOSINITDATA:LineStr>
                SMT_Var <DOSINITDATA:CFG_CommandStr>

MSG_Table_Too_Many_Parms SMT     <MSG_SYSINIT_TOO_MANY_PARMS,2>
                SMT_Var <DOSINITDATA:LineStr>
                SMT_Var <DOSINITDATA:CFG_CommandStr>

MSG_Table_Missing_Symb  SMT     <MSG_SYSINIT_MISSING_SYMB,4>
                SMT_Var <DOSINITDATA:LineStr>
                SMT_Var <DOSINITDATA:CFG_CommandStr>
                SMT_Var <DOSINITDATA:CFG_Token>
                SMT_Var <DOSINITDATA:CFG_MsgString1>
INITDATA ends


INITBSS segment

if RAS
CFG_TraceBuf    dw      0                       ;Trace buffer size (bytes)
CFG_TraceBits   db      32 dup (0)              ;Trace bits
CFG_LocalTraceBits db   32 dup (?)              ;Trace bit work area
endif ;RAS

CFG_LocalSubType db     8 dup (?)               ;DevInfo subtype work area
Config_Sys_Data dw      ?                       ;Selector of Config.Sys packets
Config_Sys_File dw      ?                       ;Selector of Config.Sys file
Config_Sys_Size dw      ?                       ;Size of Config.Sys file
Line            dw      ?                       ;Current line number
StartOfLine     dw      ?                       ;Starting address of current line
CFG_TokenFlags  dw      ?                       ;Tokenizing options
MaxTokenSize    equ     1024
CFG_Token       db      MaxTokenSize-1 dup (?)  ;Token buffer
TokenEnd        db      ?
LineStr         db      6 dup (0)               ;Line # in ASCIIZ format
CFG_TokenAddr   dw      ?                       ;Address of last token found
                                                ;in a token table
CFG_CommandAddr dw      ?                       ;Address of ASCIIZ command found
                                                ;in the token table.
CFG_CommandStr  db      MaxTokenSize dup(0)
CFG_MsgString1  db      6 dup (0)               ;Message insertion string 1
CFG_MsgString2  db      6 dup (0)               ;Message insertion string 2
INITBSS ends


INITSTRING segment
   public ConfigSysFilename
ConfigSysFilename db    'CONFIG.SYS',0          ;Name of Config.Sys file
INITSTRING ends


        FARCODE INIT
INITCODE segment


;
; SUBROUTINE NAME:  syiConfigParse
;
; DESCRIPTIVE NAME:  CONFIG.SYS parser
;
; FUNCTION:      Parse CONFIG.SYS and configure the system.
;
; NOTES:         syiConfigParse parses the information
;                and stores values.  It allocates memory and
;                stores linked lists of parsed information
;                for those CONFIG statements which do not
;                have scalar variables.
;
;                syiConfigParse may be called in
;                protect mode only.
;
; ENTRY POINT:   syiConfigParse
;    LINKAGE:    call near
;
; INPUT:         none
;
; EXIT-NORMAL:
;
;                DOSINITDATA:Config_Sys_Data  = Selector of
;                          config packet segment
;                Variables  initialized
;                Data packets  built
;
; EXIT-ERROR:    none
;
; EFFECTS:       Configuration information is filled in.
;                All registers are preserved.
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_Init
;                Config_GetToken
;                Config_ScanTable
;                Config_NextLine
;                Int2Ascii
;
; EXTERNAL REFERENCES:
;    ROUTINES:   SYIOpenFile
;                SYIReadFile
;                SYISaveMessage
;                SYIDisplayMessage
;                SYIPauseOnError
;                Config_ProcessCommand
;                SegAlloc
;                SegRealloc
;                SegFree
;
;Initialize DosGroup variables (call Config_Init)
;Open CONFIG.SYS (call SYIOpenFile)
;IF file exists and is < 64 kbytes
;        Allocate segment for CONFIG.SYS (call SegAlloc)
;        Read CONFIG.SYS (SYIReadFile)
;        Line number = 0
;        Remember where the line starts in the file
;        WHILE there exist lines in CONFIG.SYS
;                Increment line number
;                Get the command (call Config_GetToken)
;                IF token exists
;                        Select the Command token table
;                        Get the command routine (call Config_ScanTable)
;                        Process the command (call Config_ProcessCommand)
;                        IF error
;                                Save error message (call SYISaveMessage)
;                        ENDIF
;                ENDIF
;                Get the next line (call Config_NextLine)
;        ENDWHILE
;        Reallocate segment for data packets (call SegRealloc)
;        Deallocate segment for CONFIG.SYS (call SegFree)
;ENDIF
Procedure       syiConfigParse
                assume  ds:nothing,es:nothing
                SaveReg <ds,es>
                pusha
                DosInitContext <ds,es>

                call    Config_Init             ;Initialize dos variables and allocate
                                                ;segment for data packets
; int     3
                lea     di,DOSINITDATA:ConfigSysFilename
                CALLFAR SYIOpenFile     ;Open Config.Sys

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   If CONFIG.SYS doesn't exist (carry bit set) then do ALTF1 processing
;      to give user alternatives so that they can boot.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                .if <c>                         ; CONFIG.SYS exists?

                   lea     si,MSG_Table_No_Config   ;Put out no Config.Sys message
                   call    syiDisplayMessage        ;   ....
                   mov     [error_messages_displayed],1
                   call    syiPauseOnError          ;Continue when user hits 'enter'

                   .repeat
                      mov    AltFxKeyPressed,1     ; set for ALTF1 processing
                      xor    bx,bx                 ; keep screen up till keystroke
                      call   syiProcessALTF1File   ; call ALTF1 routine
                                                   ; then check if alternate
                                                   ; config.sys selected..
                                                   ; keep looping until this
                                                   ; occurs ....
                      test   AltF1Flags,ALTF1_USE_ALTERNATE_CONFIGSYS
                   .until <nz>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;  At this point an alternative config.sys has been selected;
;     We'll open it for further processing.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                   lea     di,DOSINITDATA:ConfigSysFilename
                   CALLFAR SYIOpenFile     ;Open Config.Sys
                 .endif

                .if     nc near
                   .if     <nonzero ax>         ;If the file > 64k bytes
                      lea     si,MSG_Table_Bad_Config   ;Put out bad Config.Sys message
                      call    SYISaveMessage
                   .else near                   ;Otherwise, continue processing
                     .if     <nonzero bx> near
                        mov     Config_Sys_Size,bx   ;Allocate a low movable segment
                        SaveReg <ds,es>
                        pusha
                        mov     ch,D_DATA3           ;for the Config.Sys file
                        mov     cl,SA_GDT
                        mov     di,INITOWNER
                        mov     si,HF_MOVABLE + HF_LOWMEM
                        SaveReg <ds>
                        CALLFAR SegAlloc             ;AX=handle, BX=selector
                        .if     c
                           InternalError <syiConfigParse SegAlloc failed>
                        .endif
                        RestoreReg <ds>
                        mov     Config_Sys_File,bx
                        mov     ax,bx
                        xor     bx,bx
                        xor    cx,cx
                        xor    dx,dx
                        CALLFAR SYIReadFile     ;Read the CONFIG.SYS file
                        CALLFAR SYICloseFile

                        popa
                        RestoreReg <es,ds>

                        mov     Line,0               ;Current line = 0
                        mov     ds,Config_Sys_File   ;ds -> Config.Sys file segment
                        assume  ds:nothing

                        xor     si,si                ;Begin tokenizing at the beginning
                                                     ;of the file
                       .repeat                       ;Repeat for each line in Config.Sys
                           inc     Line              ;Bump up the line number
                           mov     StartOfLine,si    ;Remember where the line began
                           xor     ax,ax             ;Get a delimited token
                           call    Config_GetToken
                           .if     nc near           ;If the token exists
                             SaveReg <ds,es>         ;Copy the token to
                             RestoreReg <ds>         ;CFG_CommandStr
                             SaveReg <ax,si,di>      ;so we can fill in messages.
                             lea   si,CFG_Token
                             lea   di,CFG_CommandStr
                             .repeat
                                lodsb
                                stosb
                             .until <zero al>
                             RestoreReg <di,si,ax>
                             RestoreReg <ds>

                             lea    bx,DOSINITDATA:CommandTable      ;look up token in the
                             call    Config_ScanTable            ;command token table
                             SaveReg ax
                             mov     ax,CFG_TokenAddr
                             mov     CFG_CommandAddr,ax
                             RestoreReg ax

                             call    Config_ProcessCommand          ;Process the command
                             .if     c               ;If an error occured,
                                push   ds
                                push   es            ;DS -> DOSINITDATA
                                pop    ds
                                push   si

                                .if     <ax eq MSG_SYSINIT_INVAL_CMD>
                                  lea     si,MSG_Table_Inval_Cmd
                                .elseif <ax eq MSG_SYSINIT_INVAL_PARM>
                                  lea     si,MSG_Table_Inval_Parm
                                .elseif <ax eq MSG_SYSINIT_MISSING_PARM>
                                  lea     si,MSG_Table_Missing_Parm
                                .elseif <ax eq MSG_SYSINIT_TOO_MANY_PARMS>
                                  lea     si,MSG_Table_Too_Many_Parms
                                .elseif <ax eq MSG_SYSINIT_MISSING_SYMB>
                                  lea     si,MSG_Table_Missing_Symb
                                .else
                                  InternalError <syiConfigParse bad message number> ;snogl
                                .endif

                                movzx  eax,Line       ;Convert line number to ASCIIZ
                                lea    di,LineStr    ;in LineStr
                                call   Int2Ascii
                                xor    al,al
                                stosb

                                call   SYISaveMessage  ;Issue the error message

                                mov    CFG_MsgString1,0    ;change min and max strings

                                pop    si
                                pop    ds
                             .endif
                           .endif
                           call    Config_NextLine   ;Advance to the next line
                        .until  c near               ;Until end of file

; 148754                        SaveReg <ds,es,ax,bx,cx,dx,di,si>
; 148754                        mov     di,Config_Sys_Data
; 148754                        mov     ds,di
; 148754                        xor     ax,ax
; 148754                        mov     bx,ds:[0].CFG_FreePtr
; 148754                        CALLFAR SegRealloc
; 148754                        .if     c
; 148754                           InternalError <syiConfigParse SegRealloc failed>
; 148754                        .endif
; 148754                        RestoreReg <si,di,dx,cx,bx,ax,es,ds>


;                      int 3
                       mov     ax,Config_Sys_File   ;Free the Config.Sys file segment
                       DosContext  <ds>,cx

                       mov  cx,_twodiskboot
                       .if <cx eq 0>                   ; _twodiskboot? NO
                          CALLFAR SegFree
                          .if     c
                              InternalError <syiConfigParse SegFree failed>
                          .endif
                       .else
                           mov     ds:_twodiskboot,ax
                       .endif
                     .endif
                   .endif
                .endif
                popa
                RestoreReg <es,ds>
                ret
EndProc         syiConfigParse

;
; SUBROUTINE NAME:  Int2Ascii
;
; DESCRIPTIVE NAME:  Integer to Ascii
;
; FUNCTION:      To convert an unsigned 32 bit integer to an
;                ASCII string
;
; NOTES:         Int2Ascii operates recursively to produce
;                an ASCII string.  Note that no trailing 0 is
;                generated (the string is not ASCIIZ)
;
; ENTRY POINT:   Int2Ascii
;    LINKAGE:    call near
;
; INPUT:
;
;                EAX        = unsigned integer to be converted
;                ES:DI     -> location to put string
;
; EXIT-NORMAL:
;
;                ES:DI     -> position immediately following
;                          the produced string
;                EAX       destroyed
;
; EXIT-ERROR:    none
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was modified to use 32 bit registers
;
;Save remainder
;Divide EAX by 10
;IF EAX is not 0
;        Call Int2Ascii recursively
;ENDIF
;Convert remainder to ASCII
;Store the character
;Restore remainder
Procedure       Int2Ascii <hybrid,far16>
                push    edx
                xor     edx,edx
                push    ecx
                mov     ecx,10
                div     ecx                    ;Divide 0:EAX by 10
                pop     ecx
                .if     <nonzero eax>          ;If the quotient is > 0
                  call    Int2Ascii            ;Recurse
                .endif
                add     dl,'0'                  ;Convert digit to ascii
                mov     al,dl                   ;Store the digit
                stosb
                pop     edx
                ret
EndProc         Int2Ascii


;
; SUBROUTINE NAME:  Config_Init
;
; DESCRIPTIVE NAME:  Initialize system configuration
;
; FUNCTION:      To initialize the DosGroup data defaults
;                which are not compile-time initialized by
;                the appropriate component.  It also
;                allocates the CONFIG.SYS data packet segment
;
; NOTES:
;
; ENTRY POINT:   Config_Init
;    LINKAGE:    call near
;
; INPUT:         none
;
; EXIT-NORMAL:   Non-compile-time default configuration
;                values are established.
;                DOSINITDATA:Config_Sys_Data = selector of
;                the CONFIG.SYS packet segment
;
; EXIT-ERROR:    none
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   SegAlloc
;
;Initialize all  DosGroup variables which do not have compile-time
;default values.
;Allocate segment for data packets
;Initialize pointers in packet segment
;Initialize the free pointer
;Set default configuration values
Procedure       Config_Init
                assume ds:DOSINITDATA,es:nothing
                pusha
                SaveReg <ds,es>
                xor     bx,bx                   ;Allocate a high, movable segment
                mov     ax,1                    ;for data packets
                mov     ch,D_DATA3
                mov     cl,SA_GDT
                mov     di,INITOWNER
                mov     si,HF_MOVABLE
                SaveReg <ds>
                CALLFAR SegAlloc
                .if     c
                   InternalError <Config_Init SegAlloc failed>
                .endif
                RestoreReg <ds>
                mov     Config_Sys_Data,bx
                mov     es,bx                   ;Initialize pointers at the

                mov     cx,size CFG_Packets / 2 ;beginning of packet segment
                xor     ax,ax
                xor     di,di
                rep     stosw

                mov     es:[0].CFG_FreePtr,size CFG_Packets     ;Initialize the free pointer

                FlatContext ds                ;Set Default configuration values
                mov     byte ptr _VMProtectedMem,1      ;Protect enabled
                DosContext ds
                .if     <[SISData].SIS_BootDrv ge 3>    ;If booted from a hard disk
                  mov     byte ptr _SMswapping,1          ;then swapping enabled
                .else
                  mov     byte ptr _SMswapping,0          ;else swapping disabled
                .endif
                DosContext ds
                mov     [_SMCFGMinFree].loword,DefaultSwap_Minfree ;Set default
                mov     [_SMCFGMinFree].hiword,0
                DosContext ds
                mov     MaxThreads,DefaultMaxThreads   ;Set max # of threads
                mov     SISData.SIS_Dynamic,DefaultDynamic ;Set dynamic priority variation
                mov     SISData.SIS_MaxWait,DefaultMaxWait      ;Set maximum wait
                mov     SISData.SIS_MinSlice,DefaultMinSlice    ;Set minimum timeslice
                mov     SISData.SIS_MaxSlice,DefaultMaxSlice    ;Set maximum timeslice
                RestoreReg <es,ds>
                popa
                ret
EndProc         Config_Init


;
; SUBROUTINE NAME:  Config_LinkPacket
;
; DESCRIPTIVE NAME:  Link a packet
;
; FUNCTION:      To link a Config.Sys packet into a given
;                list
;
; NOTES:         The packet gets linked into the given list
;                and the current line number is inserted into
;                the packet.
;
; ENTRY POINT:   Config_LinkPacket
;    LINKAGE:    call near
;
; INPUT:
;
;                DS        -> Config.Sys packet segment
;                ES        -> DOSINITDATA
;                SI        -> head/tail pointers for the
;                          desired list
;                DI        -> packet to be linked in
;
; EXIT-NORMAL:
;
;                Packet    linked into list
;                AX        destroyed
;
; EXIT-ERROR:    none
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Store line number in packet
;Set tail pointer -> packet
;IF old tail pointer = 0
;        Set head pointer -> packet
;ELSE
;        Set last packet's next -> packet
;ENDIF
;Prev pointer = old tail pointer
;Next pointer = 0
Procedure       Config_LinkPacket
                assume  ds:nothing,es:DOSINITDATA
                        ;ds ->Config_Sys_Data seg
                        ;es -> DOSINITDATA
                        ;si -> head/tail ptrs
                        ;di -> packet

                SaveReg <bx>

                movzx   eax,Line                 ;Set line number
                SaveReg <ds,es>                 ;DS <-> ES
                RestoreReg <ds,es>
                SaveReg <di>
                lea     di,[di].CFG_LineNumber  ;Store ASCIIZ line number
                call    Int2Ascii
                xor     al,al
                stosb
                RestoreReg <di>
                SaveReg <ds,es>                 ;DS <-> ES
                RestoreReg <ds,es>

                mov     ax,CFG_CommandAddr      ;get pointer to ASCIIZ command
                                                ;name found
                mov    word ptr ds:[di].CFG_Command,ax  ;store address in the packet
                mov     word ptr ds:[di].CFG_Command+2,es

                mov     bx,ds:[si].CFG_Tail     ;link into:
                mov     ds:[si].CFG_Tail,di         ;tail ptr
                .if     <zero bx>
                   mov     ds:[si].CFG_Head,di      ;head ptr
                .else
                   mov     ds:[bx].CFG_Next,di      ;prev's next
                .endif
                mov     ds:[di].CFG_Prev,bx     ;Set prev ptr
                mov     ds:[di].CFG_Next,0      ;Set next ptr
                RestoreReg <bx>
                ret
EndProc         Config_LinkPacket


;
; SUBROUTINE NAME:  Config_GetToken
;
; DESCRIPTIVE NAME:  Get a token
;
; FUNCTION:      To isolate a token from a line in CONFIG.SYS
;
; NOTES:         Config_GetToken is a semantic procedure
;                which isolates a token and creates an
;                upshifted ASCIIZ string at
;                DOSINITDATA:Token.  The token may be a
;                maximum of 127 characters.  Either delimited
;                (by blanks, tabs, or special characters)
;                tokens or nondelimited (to the end of the
;                line) may be found.  The special characters
;                =,() are recognized as tokens.
;
; ENTRY POINT:   Config_GetToken
;    LINKAGE:    call near
;
; INPUT:
;
;                AX        = 0 for an uppercase delimited token
;                          = 1 for an uppercase nondelimited
;                              token
;                          = 2 for a mixed case delimited token
;                          = 3 for a mixed case nondelimited
;                              token
;                DS:SI     -> location to start scanning for
;                          a token
;                ES:       addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                Token     The first 127 characters of the
;                          token
;                DS:SI     -> the position to begin scanning
;                          for the next token
;
; EXIT-ERROR:
;
;                Carry     set
;                Token     ASCIIZ null string
;                DS:SI     -> the position to begin scanning
;                          for the next token
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetChar
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;IF ax = 0 or 2 then change to GetToken state
;IF ax = 1 or 3 then change to GetString state
;
;State GetString
;        Get a char (call Config_GetChar)
;        IF eof or eoln THEN change to TokenNotFound state
;        Change to CopyStringToken state
;
;State CopyStringToken
;        IF eoln THEN change to TokenFound state
;        IF " ignore Get next char
;        IF case folding then upshift char
;        IF there is space for the char THEN store the char
;        Get the next char (call Config_GetChar)
;        IF eof THEN change to TokenFound state
;        Repeat
;
;State GetToken
;        Get a char (call Config_GetChar)
;        IF eof Then change to TokenNotFound state
;        IF char is " THEN change to DquoteToken state
;        IF char is one of =,() THEN change to SpecialToken state
;        IF eoln THEN change to TokenNotFound state
;        IF char is not blank or tab THEN change to CopyToken state
;        Repeat
;
;State DquoteToken
;        Get a char (call Config_GetChar)
;        IF char is " THEN Get next char change to copytoken state
;        IF case folding then upshift char
;        IF space for char THEN store char
;        Repeat
;
;State SpecialToken
;        Store char
;        Get next char
;        Change to TokenFound state
;
;State CopyToken
;        IF char = a delimiter THEN change to TokenFound state
;        IF case folding then upshift char
;        IF space for char THEN store char
;        Get next char (call Config_GetChar)
;        IF " THEN change to DquoteToken state
;        IF eof THEN change to TokenFound state
;        Repeat
;
;State TokenFound
;        Make token ASCIIZ
;        Backup a char
;        Clear carry
;        Change to GetTokenEnd state
;
;State TokenNotFound
;        Restore SI
;        Set error code
;        Set carry
;        Change to GetTokenEnd state
;
;State GetTokenEnd
;        Return
Procedure       Config_GetToken
                assume ds:nothing,es:DOSINITDATA
                push    di
                push    si

                lea     di,CFG_Token            ;Put token at CFG_Token
                mov     CFG_TokenFlags,ax
                test    ax,1                    ;Test for delimited/nondelimited scan
                nextstate GetToken z
                nextstate GetString nz

state           GetString
                call    Config_GetChar          ;Get a character
                nextstate TokenNotFound c       ;If eof then token not found
                nextstate TokenNotFound al cr   ;If eoln then token not found
                nextstate CopyStringToken       ;Get an undelimited token
endstate        GetString

state           CopyStringToken
                nextstate TokenFound al cr      ;If eoln then token found
                .if     <bit CFG_TokenFlags nand 10b> and  ;Check for case fold
                .if     <al ae 'a'> and         ;Upshift the char
                .if     <al be 'z'>
                  and al,not 32
                .endif

                .if     <di ae <offset DOSINITDATA:TokenEnd>>  ;if out of space
                  nextstate TokenTooLong
                .endif
                stosb                                         ;Store the char
                call    Config_GetChar          ;Get the next char
                nextstate TokenFound c          ;if eof then token found
endstate        CopyStringToken repeat          ;repeat

state           GetToken                        ;Get a delimited token
                call    Config_GetChar          ;Get a char
                nextstate TokenNotFound c       ;If eof then token not found
                nextstate DquoteToken al <dquote>
                                                ;### DCR 687 ###
                                                ;### Include " for blanks in
                                                ;### file names
                nextstate SpecialToken al <comma,equals,open,close>
                                                ;Process ,=() specially
                nextstate TokenNotFound al cr   ;if eoln then token not found
                nextstate CopyToken al <blank,tab> exclude
                                                ;if not white space then get token
endstate        GetToken repeat                 ;repeat

                                                ;### DCR 687 ###
state           DquoteToken                     ;### Get a file name with embedded blanks
                call    Config_GetChar          ;### Get the next char
                nextstate TokenNotFound c       ;### if eof then token not found
                .if <al eq dquote>              ;### If " then end of name
                   call    Config_GetChar       ;### Get the next char
                   nextstate CopyToken
                .endif
                .if     <bit CFG_TokenFlags nand 10b> and  ;### Check for case fold
                .if     <al ae 'a'> and         ;### Upshift char
                .if     <al be 'z'>
                  and al,not 32
                .endif

                .if     <di ae <offset DOSINITDATA:TokenEnd>>  ;### if out of space
                  nextstate TokenTooLong
                .endif
                stosb                           ;### Store char
endstate        DquoteToken repeat              ;### repeat
                                                ;### DCR 687 ###

state           SpecialToken                    ;Get a special char token
                stosb                           ;Store the special char
                lodsb                           ;Advance to the next char
                nextstate TokenFound            ;Token found
endstate        SpecialToken

state           CopyToken                       ;Copy the token
                nextstate TokenFound al <blank,tab,comma,equals,cr,open,close>
                                                ;if a delimiter then token found
                .if     <bit CFG_TokenFlags nand 10b> and  ;Check for case fold
                .if     <al ae 'a'> and         ;Upshift char
                .if     <al be 'z'>
                  and al,not 32
                .endif

                .if     <di ae <offset DOSINITDATA:TokenEnd>>  ;if out of space
                  nextstate TokenTooLong
                .endif
                stosb                                         ;Store char
                call    Config_GetChar          ;Get the next char
                nextstate TokenFound c          ;if eof then token found
                nextstate DquoteToken al <dquote>
                                                ;### DCR 687 ###
                                                ;### Include " for blanks in
                                                ;### file names
endstate        CopyToken repeat                ;repeat

state           TokenFound                      ;Token has been found
                xor     al,al                   ;Make token ASCIIZ
                stosb
                dec     si                      ;Backup a char
                pop     di                      ;Eat the pushed si
                pop     di
                clc                             ;Indicate no error
                nextstate GetTokenEnd
endstate        TokenFound

state           TokenNotFound                   ;Token was not found
                pop     si                      ;restore si
                pop     di
                mov     CFG_Token,0             ;store null token
                mov     ax,MSG_SYSINIT_MISSING_PARM
                stc                             ;Indicate missing parameter
                nextstate GetTokenEnd
endstate        TokenNotFound

state           TokenTooLong
                xor     al,al
                stosb
                pop     si
                pop     di
                mov     ax,MSG_SYSINIT_INVAL_PARM
                stc
                nextstate GetTokenEnd
endstate        TokenTooLong

state           GetTokenEnd
                ret
endstate        GetTokenEnd
EndProc         Config_GetToken


;
; SUBROUTINE NAME:  Config_ScanTable
;
; DESCRIPTIVE NAME:  Scan a token table
;
; FUNCTION:      To locate a token in a given token table and
;                return associated information.
;
; NOTES:         Token tables must be in the InitCode group.
;
; ENTRY POINT:   Config_ScanTable
;    LINKAGE:    call near
;
; INPUT:
;
;                ES        addresses DOSINITDATA
;                DOSINITDATA:BX  -> Token table to use for
;                          lookup
;                DOSINITDATA:Token  =  Uppercase ASCIIZ token
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        =  The number associated with the
;                          token found.
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        = The number associated with the
;                          terminating token table entry.
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_StringCompare
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;REPEAT
;        Get table entry
;        IF end of table
;                Associate not found value
;                Set carry
;                Exit loop
;        ENDIF
;        Compare strings (call Config_StringCompare)
;        IF equal
;                Associate value
;                Clear carry
;                Exit loop
;        ENDIF
;        Index next entry
;FOREVER
Procedure       Config_ScanTable
                assume  ds:nothing,es:DOSINITDATA
                push    ds
                push    bx
                push    si
                push    di
                DosInitContext ds

                .repeat                         ;Scan for token in given table
                  mov     si,ds:[bx].TokenString        ;Address reference string
                  .if     <zero si>                     ;If end of table
                    mov     ax,ds:[bx].TokenValue         ;Associate default value
                    stc                                   ;Indicate error
                    .leave                                ;Exit loop
                  .endif
                  lea     di,DOSINITDATA:CFG_Token      ;Address found token
                  call    Config_CompareStrings         ;Compare strings
                  .if     eq                            ;If match found
                    mov     ax,ds:[bx].TokenString        ;get address of string
                    mov     CFG_TokenAddr,ax              ;remember command found
                    mov     ax,ds:[bx].TokenValue         ;Associate appropriate value
                    clc                                   ;Indicate no error
                    .leave                                ;Exit loop
                  .endif
                  add     bx,size TokenStruc            ;Get next table entry
                .until                          ;Continue scanning

                pop     di
                pop     si
                pop     bx
                pop     ds
                assume  ds:nothing
                ret
EndProc         Config_ScanTable


;
; SUBROUTINE NAME:  Config_CompareStrings
;
; DESCRIPTIVE NAME:  Compare strings
;
; FUNCTION:      To compare two ASCIIZ strings for identity.
;
; NOTES:         Case is significant.
;
; ENTRY POINT:   Config_CompareStrings
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> string 1
;                ES:DI     -> string 2
; EXIT-NORMAL:
;
;                Equal     if the strings are identical
;                NotEqual  if the strings are different
;
; EXIT-ERROR:    none
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;REPEAT
;        Compare characters
;UNTIL mismatch or end of string1 found
Procedure       Config_CompareStrings
                assume ds:nothing,es:nothing
                .repeat                         ;Repeat
                  lodsb                           ;compare chars
                  scasb
                .until nz or                    ;until mismatch
                .until <zero al>                ;or until end of string
                ret
EndProc         Config_CompareStrings

;
; SUBROUTINE NAME:  Config_RangeCheck
;
; DESCRIPTIVE NAME:  Range check for 32 bit numbers
;
; FUNCTION:      To verify that a number is in a given
;                range.
;
; NOTES:
;
; ENTRY POINT:   Config_RangeCheck
;    LINKAGE:    call near
;
; INPUT:
;
;                EAX        = the number to be checked
;                ECX        = the range minimum
;                EDX        = the range maximum
;
; EXIT-NORMAL:
;
;                Carry     clear
;                EAX        preserved
;
; EXIT-ERROR:
;
;                Carry     set
;                EAX        = error code
;                CFG_Token  = ASCIIZ string of input AX
;                CFG_MsgString1  = ASCIIZ string of input ECX
;                CFG_MsgString2  = ASCIIZ string of input EDX
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Int2Ascii
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was modified to use 32 bit registers
;
;IF value out of range
;        Convert EAX to ASCIIZ string at CFG_Token (call Int2Ascii)
;        Convert ECX to ASCIIZ string at CFG_MsgString1 (call Int2Ascii)
;        Convert EDX to ASCIIZ string at CFG_MsgString2 (call Int2Ascii)
;        Set carry
;ELSE
;        Clear carry
;ENDIF
Procedure       Config_RangeCheck
                assume  ds:nothing,es:DOSINITDATA
                ;es:DOSINITDATA
                ;eax between ecx,edx

                .if     <eax b ecx> or            ;If value below minimum or
                .if     <eax a edx>               ;If above maximum
                  push    di

                  lea     di,DOSINITDATA:CFG_Token      ;Convert value to
                  call    Int2Ascii                     ;ASCIIZ string at CFG_TOKEN
                  xor     al,al
                  stosb

                  mov     eax,ecx
                  lea     di,DOSINITDATA:CFG_MsgString1 ;Convert minimum value to
                  call    Int2Ascii                     ;ASCIIZ string at CFG_MsgString1
                  xor     al,al
                  stosb

                  mov     eax,edx
                  lea     di,DOSINITDATA:CFG_MsgString2 ;Convert maximum value to
                  call    Int2Ascii                     ;ASCIIZ string at CFG_MsgString2
                  xor     al,al
                  stosb

                  pop     di
                  stc
                  mov     ax,MSG_SYSINIT_INVAL_PARM     ;error--out of range
                .else                           ;Else
                  clc                                   ;no error
                .endif                          ;Endif

                ret
EndProc         Config_RangeCheck

;
; SUBROUTINE NAME:  Config_NextLine
;
; DESCRIPTIVE NAME:  Next line
;
; FUNCTION:      To advance to the next line of CONFIG.SYS
;
; NOTES:
;
; ENTRY POINT:   Config_NextLine
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> any position in the line
;                ES        addresses DosGroup
;
; EXIT-NORMAL:
;
;                Carry     clear
;                DS:SI     -> beginning of the next line
;
; EXIT-ERROR:
;
;                Carry     set (end of file)
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;REPEAT
;        Get char (call Config_GetChar)
;UNTIL eof OR char = linefeed
Procedure       Config_NextLine
                assume ds:nothing,es:DOSINITDATA
                .repeat                         ;Repeat
                  call    Config_GetChar          ;Get a char
                .until c or                     ;Until end of file
                .until <al eq lf>               ;or end of line
                ret
EndProc         Config_NextLine


;
; SUBROUTINE NAME:  Config_GetChar
;
; DESCRIPTIVE NAME:  Get a character
;
; FUNCTION:      To get a character, checking for EOF
;
; NOTES:
;
; ENTRY POINT:   Config_GetChar
;    LINKAGE:    call near
;
; INPUT:
;                DS:SI     -> character in Config.Sys file
;                          segment
;                ES:Config_Sys_Size  = the size of the
;                          Config.Sys file
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AL        = char
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        destroyed
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get the next char
;IF past size of file or
;IF char is an EOF character
;        Set carry
;ELSE
;        Clear carry
;ENDIF
Procedure       Config_GetChar,NEAR,LOCAL
                assume  ds:nothing,es:DOSINITDATA
                .if     <si ae Config_Sys_Size>         ;If last byte in file
                  inc     si                              ;pretend we read a char
                  stc                                     ;and discovered EOF
                .else
                  lodsb                                   ;Get a char
                  .if     <al eq eof>                     ;or is an eof char
                    stc                                     ;Indicate error
                  .else                                   ;else
                    clc                                     ;Indicate no error
                  .endif
                .endif
                ret
EndProc         Config_GetChar


;
; SUBROUTINE NAME:  Config_GetNumber
;
; DESCRIPTIVE NAME:  Set up to get a number token
;
; FUNCTION:      Set up to get a short number
;                range 0-65535.
;
; NOTES:
;
; ENTRY POINT:   Config_GetNumber
;    LINKAGE:    call near
;
; INPUT:
;
; EXIT-NORMAL:
;
; EXIT-ERROR:
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:
;                Config_wNumber
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was modified to use a worker routine to get
;     the actual number.  This routine informs Config_wNumber
;     to check that the number does not grow larger than 64K.
;
;set bl to 1 (Used by Config_wNumber to determine that the number
;             should not be greater than 64k
;Get number (call Config_wNumber)
;
;        Return
Procedure       Config_GetNumber
                assume  ds:nothing,es:DOSINITDATA

                push    ebx
                mov     bl,1
                call    Config_wNumber
                pop     ebx
                ret
EndProc         Config_GetNumber

;
; SUBROUTINE NAME:  Config_GetLongNumber
;
; DESCRIPTIVE NAME:  Set up to get a number token
;
; FUNCTION:      Set up to get a long number
;                range 0-(2**32) - 1.
;
; NOTES:
;
; ENTRY POINT:   Config_GetLongNumber
;    LINKAGE:    call near
;
; INPUT:
;
; EXIT-NORMAL:
;
;
; EXIT-ERROR:
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_wNumber
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was modified to use a worker routine to get
;     the actual number.  This routine informs Config_wNumber
;     that the number can be larger than 64K.
;
;set bl to 0 (Used by Config_wNumber to determine that the number
;             can be greater than 64k
;Get number (call Config_wNumber)
;
;        Return
Procedure       Config_GetLongNumber
                assume  ds:nothing,es:DOSINITDATA

                push    ebx
                mov     bl,0
                call    Config_wNumber
                pop     ebx
                ret
EndProc         Config_GetLongNumber


;
; SUBROUTINE NAME:  Config_wNumber
;
; DESCRIPTIVE NAME:  Get a number token
;
; FUNCTION:      To get and consume a number token in the
;                range 0-(2**32) - 1.
;
; NOTES:
;
; ENTRY POINT:   Config_wNumber
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;
; EXIT-NORMAL:
;
;                Carry     clear
;                EAX       = number found
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                EAX       = error code (no number or
;                            overflow)
;                Token     = invalid token
;                DS:SI       unchanged
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was created from Config_GetNumber to get
;     number tokens in the range 0-((2**32)-1).  Based on the
;     value of bl (set to Check64k) this routine will return
;     a carry if number is > 64k (bl = 1).  This was to
;     accomodate when Config_GetNumber returned a carry if
;     the number was > 64K.
;     This process uses 32 bit registers.
;
;Number = 0
;Get token (call Config_GetToken)
;IF no token THEN change to NumberNotFound state
;Get first char of token
;Change to BuildNumber state
;
;State BuildNumber
;        IF not '0' <= char <= '9' THEN change to BadNumberFound state
;        Convert char to binary
;        Number = number * 10 + binary char
;        IF overflow THEN change to BadNumberFound state
;        Get next char
;        IF end of token THEN chage to NumberFound state
;        Repeat
;
;State BadNumberFound
;        Set error code
;        Set carry
;        Change to GetNumberEnd state
;
;State NumberNotFound
;        Set error code
;        Set carry
;        Change to GetNumberEnd state
;
;State NumberFound
;        Clear carry
;        Change to GetNumberEnd state
;
;State GetNumberEnd
;        Return
Procedure       Config_wNumber
                assume  ds:nothing,es:DOSINITDATA
                LocalVar   Check64k,BYTE
                EnterProc
state           GetNumber

                mov     Check64k,bl
                push    ds
                push    ecx
                push    edx
                push    si
                xor     ebx,ebx
                mov     bx,10
                xor     ecx,ecx
                xor     eax,eax                   ;Get a delimited token
                call    Config_GetToken
                push    si
                nextstate NumberNotFound c      ;If no token then number not found
                push    es                      ;DS -> DOSINITDATA
                pop     ds
                lea     si,DOSINITDATA:CFG_Token ;DS:SI -> token
                lodsb                           ;Get first char of token
                nextstate BuildNumber
endstate        GetNumber

state           BuildNumber                     ;Calculate number
                nextstate BadNumberFound al <'0','9'> range exclude
                                                ;If char not in range '0'..'9'
                                                ;then the token is bad
                sub     eax,'0'                 ;Convert digit to binary
                xchg    eax,ecx
                mul     ebx                     ;Number = Number * 10
                add     ecx,eax                 ;Number = Number + digit
                .if     c or                    ;If overflow or
                .if     <nonzero edx> or           ;if > 2**32 -1
                .if     <Check64k eq 1> and
                .if     <ecx a 0ffffh>          ; if > 64k
                  nextstate BadNumberFound      ;then number is bad
                .endif
                xor     eax,eax
                lodsb                           ;Get the next char
                nextstate NumberFound al 0      ;If end of token then number is found
endstate        BuildNumber repeat              ;Repeat

state           BadNumberFound                  ;Bad number encountered
                pop     si                      ;Eat recent SI
                pop     si                      ;Restore SI
                mov     ax,MSG_SYSINIT_INVAL_PARM
                stc                             ;Indicate invalid parameter error
                nextstate GetNumberEnd
endstate        BadNumberFound

state           NumberNotFound
                pop     si                      ;Eat recent SI
                pop     si                      ;Restore SI
                mov     ax,MSG_SYSINIT_MISSING_PARM
                stc                             ;Indicate missing parameter error
                nextstate GetNumberEnd
endstate        NumberNotFound

state           NumberFound
                pop     si                      ;Restore SI
                pop     ax                      ;Eat previous SI
                mov     eax,ecx                 ;Return number
                clc                             ;No error
                nextstate GetNumberEnd
endstate        NumberFound

state           GetNumberEnd
                pop     edx
                pop     ecx
                pop     ds
                LeaveProc
                ret
endstate        GetNumberEnd
EndProc         Config_wNumber


;
; SUBROUTINE NAME:  Config_GetEqualSign
;
; DESCRIPTIVE NAME:  Get an equal sign token
;
; FUNCTION:      To verify that the next token is an "=" and
;                consume it.
;
; NOTES:
;
; ENTRY POINT:   Config_GetEqualSign
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        undefined
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;
;Get a delimited token (call Config_GetToken)
;IF token not found
;       Restore SI
;ELSE
;       IF token is an equal sign
;               Clear carry
;       ELSE
;               Restore SI
;               Set error code
;               Set carry
;       ENDIF
;ENDIF
Procedure       Config_GetEqualSign
                assume  ds:nothing,es:DOSINITDATA
                push    si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                .if     c                       ;If no token found
                  pop     si
                .else
                  .if     <CFG_Token eq equals>   ;and is an equal sign
                    pop     ax                      ;Then no error
                    clc
                  .else                           ;Else
                    pop     si                      ;Restore SI
                    mov     word ptr CFG_MsgString1,equals
                    mov     ax,MSG_SYSINIT_MISSING_SYMB
                    stc                             ;Indicate Missing symbol error
                  .endif
                .endif
                ret
EndProc         Config_GetEqualSign


;
; SUBROUTINE NAME:  Config_GetComma
;
; DESCRIPTIVE NAME:  Get a comma
;
; FUNCTION:      To verify that the next token is a "," and
;                consume it.
;
; NOTES:
;
; ENTRY POINT:   Config_GetComma
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES:       addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        undefined
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        = error code (no token)
;                DS:SI     unchanged
;                Token     = ASCIIZ null
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a delimited token (call Config_GetToken)
;IF token not found
;       Restore SI
;ELSE
;       IF token is not a comma
;               Restore SI
;       ENDIF
;       Clear carry
;ENDIF
Procedure       Config_GetComma
                assume  ds:nothing,es:DOSINITDATA
                push    si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                .if     c                       ;If no token found
                  pop     si
                .else
                  .if     <CFG_Token eq comma>    ;and is a comma
                    pop     ax                      ;Then no error
                  .else                           ;Else
                    pop     si                      ;Restore SI
                  .endif
                  clc
                .endif
                ret
EndProc         Config_GetComma


;
; SUBROUTINE NAME:  Config_GetOpenParen
;
; DESCRIPTIVE NAME:  Get a OpenParen
;
; FUNCTION:      To verify that the next token is a "(" and
;                consume it.
;
; NOTES:
;
; ENTRY POINT:   Config_GetOpenParen
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES:       addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        undefined
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a delimited token (call Config_GetToken)
;IF token not found
;       Restore SI
;ELSE
;       IF token is an open paren
;               Clear carry
;       ELSE
;               Restore SI
;               Set error code
;               Set carry
;       ENDIF
;ENDIF
Procedure       Config_GetOpenParen
                assume  ds:nothing,es:DOSINITDATA
                push    si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                .if     c                       ;If no token found
                  pop     si
                .else
                  .if     <CFG_Token eq open>     ;and is an open paren
                    pop     ax                      ;Then no error
                    clc
                  .else                           ;Else
                    pop     si                      ;Restore SI
                    mov     word ptr CFG_MsgString1,open
                    mov     ax,MSG_SYSINIT_MISSING_SYMB
                    stc                             ;Indicate Missing symbol error
                  .endif
                .endif
                ret
EndProc         Config_GetOpenParen


;
; SUBROUTINE NAME:  Config_GetCloseParen
;
; DESCRIPTIVE NAME:  Get a CloseParen
;
; FUNCTION:      To verify that the next token is a ")" and
;                consume it.
;
; NOTES:
;
; ENTRY POINT:   Config_GetCloseParen
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        undefined
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a delimited token (call Config_GetToken)
;IF token not found
;       Restore SI
;ELSE
;       IF token is a close paren
;               Clear carry
;       ELSE
;               Restore SI
;               Set error code
;               Set carry
;       ENDIF
;ENDIF
Procedure       Config_GetCloseParen
                assume  ds:nothing,es:DOSINITDATA
                push    si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                .if     c                       ;If no token found
                  pop     si
                .else
                  .if     <CFG_Token eq close>    ;and is an open paren
                    pop     ax                      ;Then no error
                    clc
                  .else                           ;Else
                    pop     si                      ;Restore SI
                    mov     word ptr CFG_MsgString1,close
                    mov     ax,MSG_SYSINIT_MISSING_SYMB
                    stc                             ;Indicate Missing symbol error
                  .endif
                .endif
                ret
EndProc         Config_GetCloseParen


;
; SUBROUTINE NAME:  Config_GetEndOfLine
;
; DESCRIPTIVE NAME:  Get an end of line
;
; FUNCTION:      To verify that no more tokens exist on the
;                current line
;
; NOTES:
;
; ENTRY POINT:   Config_GetEndOfLine
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for EOL
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        undefined
;                DS:SI     unchanged
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        = error code
;                DS:SI     unchanged
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Remember SI
;Get a delimited token (call Config_GetToken)
;IF line is too long or
;IF token found
;        Restore SI
;        Set error code
;        Set carry
;ELSE
;        Clear carry
;ENDIF
Procedure       Config_GetEndOfLine
                assume  ds:nothing,es:DOSINITDATA
                LocalVar SavedSI,WORD
                EnterProc
                mov     SavedSI,si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                mov     ax,si
                sub     ax,StartOfLine
                .if     <ax ae MaxTokenSize> or ;If the line is too long or
                .if     <CFG_Token ne 0>         ;If token found
                  mov     si,SavedSI              ;Restore SI
                  mov     ax,MSG_SYSINIT_TOO_MANY_PARMS ;Set error code
                  stc                             ;Indicate error
                .else                           ;Else
                  clc                             ;Indicate no error
                .endif                          ;Endif
                LeaveProc
                ret
EndProc         Config_GetEndOfLine


;
; SUBROUTINE NAME:  Config_VerifyToken
;
; DESCRIPTIVE NAME:  Verify token
;
; FUNCTION:      To get and verify that a token is of a given
;                token table.
;
; NOTES:
;
; ENTRY POINT:   Config_VerifyToken
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> token to get
;                ES        -> DOSINITDATA
;                BX        -> token table to use
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        = value associated with token
;                DS:SI     -> next token
;                ES:CFG_Token  = ASCIIZ token found
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        error code
;                DS:SI     unchanged
;                ES:CFG_Token  invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;                Config_ScanTable
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Save SI
;Get a delimited token (call Config_GetToken)
;IF token exists
;        Scan table for token (call Config_ScanTable)
;ENDIF
;IF carry
;        Restore SI
;ELSE
;        Discard old SI
;ENDIF
Procedure       Config_VerifyToken,NEAR,LOCAL
                push    si
                xor     ax,ax                   ;Get a delimited token
                call    Config_GetToken
                .if     nc                      ;If token exists
                  call    Config_ScanTable        ;Look token up in token table
                .endif
                .if     c                       ;If error
                  pop     si                      ;Restore SI
                .else                           ;Else
                  add     sp,2                    ;Eat SI
                .endif                          ;Endif
                ret
EndProc         Config_VerifyToken

IF    RAS                                                              ;83839
;                                                                      ;78486
; SUBROUTINE NAME:  Config_GetTrapdump                                 ;78486
;                                                                      ;78486
; DESCRIPTIVE NAME:  Get parameter of TRAPDUMP command                 ;78486
;                                                                      ;78486
; FUNCTION:      To verify and consume a "YES", "NO" or "R0"           ;78486
;                token.                                                ;78486
;                                                                      ;78486
; NOTES:                                                               ;78486
;                                                                      ;78486
; ENTRY POINT:   Config_GetTrapdump                                    ;78486
;    LINKAGE:    call near                                             ;78486
;                                                                      ;78486
; INPUT:                                                               ;78486
;                                                                      ;78486
;                DS:SI     -> position to scan for token               ;78486
;                ES        addresses DOSINITDATA                       ;78486
;                                                                      ;78486
; EXIT-NORMAL:                                                         ;78486
;                                                                      ;78486
;                Carry     Clear                                       ;78486
;                AX        = token (0=NO, 1=YES 2=DUMP)                ;78486
;                DS:SI     -> position to scan for next token          ;78486
;                                                                      ;78486
; EXIT-ERROR:                                                          ;78486
;                                                                      ;78486
;                Carry     Set                                         ;78486
;                AX        = error code                                ;78486
;                DS:SI     unchanged                                   ;78486
;                Token     = invalid token                             ;78486
;                                                                      ;78486
; EFFECTS:       none                                                  ;78486
;                                                                      ;78486
; INTERNAL REFERENCES:                                                 ;78486
;    ROUTINES:   Config_VerifyToken                                    ;78486
;                                                                      ;78486
; EXTERNAL REFERENCES:                                                 ;78486
;    ROUTINES:   none                                                  ;78486
;                                                                      ;78486
;Address Reipl token table                                             ;78486
;Verify token (call Config_VerifyToken)                                ;78486
Procedure       Config_GetTrapdump                                     ;78486
                push    bx                                             ;78486
                lea     bx,DOSINITDATA:TrapdumpTable ;Addr.Yes/No/R0 table
                call    Config_VerifyToken           ;Get and verify the token
                pop     bx                                             ;78486
                ret                                                    ;78486
EndProc         Config_GetTrapdump                                     ;78486
ENDIF    ; RAS                                                         ;83839

;
; SUBROUTINE NAME:  Config_GetYesNo
;
; DESCRIPTIVE NAME:  Get a Yes or No
;
; FUNCTION:      To verify and consume a "YES" or "NO"
;                token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetYesNo
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (0=NO, 1=YES)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address Yes/No token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetYesNo
                push    bx
                lea     bx,DOSINITDATA:YesNoTable       ;Address Yes/No table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetYesNo


;
; SUBROUTINE NAME:  Config_GetOnOff
;
; DESCRIPTIVE NAME:  Get a On or Off
;
; FUNCTION:      To verify and consume a "ON" or "OFF"
;                token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetOnOff
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (0=OFF, 1=ON)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address On/Off token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetOnOff
                push    bx
                lea     bx,DOSINITDATA:OnOffTable       ;Address On/Off table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetOnOff

;
; SUBROUTINE NAME:  Config_GetUmbNoUmb
;
; DESCRIPTIVE NAME:  Get UMB or NOUMB value
;
; FUNCTION:      To verify and consume a "UMB" or "NOUMB"
;                token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetUmbNoUmb
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (0=NOUMB, 1=UMB)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address UMB token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetDosFlags                                                  ;BC002
                push    bx                                                          ;BN001
                lea     bx,DOSINITDATA:UMBTable         ;Address UMB table          ;BN001
                call    Config_VerifyToken              ;Get and verify the token   ;BN001
                pop     bx                                                          ;BN001
                ret                                                                 ;BN001
EndProc         Config_GetDosFlags                                                  ;BC002


;
;
; SUBROUTINE NAME:  Config_GetMemManToken
;
; DESCRIPTIVE NAME:  Get a token from MemMan line
;
; FUNCTION:      To verify and consume token from the MemMan line
;
; NOTES:
;
; ENTRY POINT:   Config_GetMemManToken
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        token found (see INITOKEN.ASM/INICFG.INC)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        error code
;                DS:SI     unchanged
;                Token     invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;
;Address MemMan token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetMemManToken
                push    bx
                lea     bx,DOSINITDATA:MemManTable   ;Address the MemMan table
                call    Config_VerifyToken           ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetMemManToken


;
; SUBROUTINE NAME:  Config_GetAbsDyn
;
; DESCRIPTIVE NAME:  Get an ABSOLUTE or DYNAMIC token
;
; FUNCTION:      To verify and consume an ABSOLUTE or DYNAMIC
;                token
;
; NOTES:
;
; ENTRY POINT:   Config_GetAbsDyn
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        token found (0=ABSOLUTE,
;                          1=DYNAMIC)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        undefined
;                DS:SI     unchanged
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address Absolute/Dynamic token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetAbsDyn
                push    bx
                lea    bx,DOSINITDATA:AbsDynTable       ;Address the Absolute/Dynamic table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetAbsDyn


;
; SUBROUTINE NAME:  Config_GetCodePage
;
; DESCRIPTIVE NAME:  Get a code page
;
; FUNCTION:      To get a code page token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetCodePage
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        = code page
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        error code
;                DS:SI     unchanged
;                Token     invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a number
;If something bad was found
;       Set invalid codepage error
;Endif
Procedure       Config_GetCodePage
                call    Config_GetNumber                ;Get a number
                .if     c                               ;If something bad
                  .if     <ax ne MSG_SYSINIT_MISSING_PARM> ;If something was found
                    mov     ax,MSG_SYSINIT_INVAL_PARM         ;Set codepage error
                  .endif                                  ;Endif
                  stc                                     ;Reset carry
                .endif                                  ;Endif
                ret
EndProc         Config_GetCodePage


;
; SUBROUTINE NAME:  Config_GetCountry
;
; DESCRIPTIVE NAME:  Get a Country code
;
; FUNCTION:      To get a code page token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetCountry
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        = country code
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        error code
;                DS:SI     unchanged
;                Token     invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetNumber
;                Config_RangeCheck
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a number (call Config_GetNumber)
;Validate range (call Config_RangeCheck
Procedure       Config_GetCountry
                call    Config_GetNumber
                .if     nc
                    push    ecx                         ;@DB69882
                    push    edx                         ;@DB69882
                    mov     ecx,MinCountry              ;@DB69882
                    mov     edx,MaxCountry              ;@DB69882
                    call    Config_RangeCheck
                    pop     edx                         ;@DB69882
                    pop     ecx                         ;@DB69882
                .endif
                ret
EndProc         Config_GetCountry

;
; SUBROUTINE NAME:  Config_GetDiskThresh
;
; DESCRIPTIVE NAME:  Get Disk Cache Threshold
;
; FUNCTION:      To get the DiskCache Threshold token
;
; NOTES:
;
; ENTRY POINT:   Config_GetDiskThresh
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     clear
;                AX        = disk cache threshold
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                AX        error code
;                DS:SI     unchanged
;                Token     invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetNumber
;                Config_RangeCheck
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a number (call Config_GetNumber)
;Validate range (call Config_RangeCheck
Procedure       Config_GetDiskThresh
                call    Config_GetNumber
                .if     nc
                    push    cx
                    push    dx
                    mov     cx,MinDiskThresh    ;                        ;@9312
                    mov     dx,MaxDiskThresh    ;                        ;@9312
                    call    Config_RangeCheck
                    .if     c
                      xor   ax,ax               ; special out-of-range
                      stc
                    .endif
                    pop     dx
                    pop     cx
                .endif
                ret
EndProc         Config_GetDiskThresh

;
; SUBROUTINE NAME:  Config_GetLazyWrite
;
; DESCRIPTIVE NAME:  Get a LW  token
;
; FUNCTION:      To verify and consume a "LW" token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetLazyWrite
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (1=LW)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address Rom token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetLazyWrite
                push    bx
                lea     bx,DOSINITDATA:LWTable          ;Address the LW table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetLazyWrite

;
; SUBROUTINE NAME:  Config_GetAutoCheck
;
; DESCRIPTIVE NAME:  Get a AC  token
;
; FUNCTION:      To verify and consume a "AC" token.
;
; NOTES:
;
; ENTRY POINT:   Config_AutoCheck
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (1=AC)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address token table
;Verify token (call Config_VerifyToken)
Procedure Config_GetAutoCheck
     assume ds:nothing,es:DOSINITDATA
     push    bx
     push    cx
     push    di
     push    si

     lea     di,CFG_Token            ;Put token at CFG_Token
     mov     CFG_TokenFlags,1
     mov     bl,'A'
     xor     cx,cx
     xor     ax,ax
     .repeat
       call     Config_GetChar
       inc      cl
       .if   nc
           .if <al eq comma>
               mov  cl,5                   ;make loop stop with error
           .else
               .if   <cl eq 3>    and
               .if   <al eq ':'>
                     stosb                 ;Store char
                     xor     al,al         ;Make token ASCIIZ
                     stosb
                     pop     di            ;Eat the pushed si
                     pop     di
                     clc                   ;Indicate no error
                     mov  bl,0
               .else
                 .if <bit CFG_TokenFlags nand 10b> and  ;Check for case fold
                 .if <al ae 'a'> and         ;Upshift char
                 .if <al be 'z'>
                     and al,not 32
                 .endif
                 .if     <al eq bl>
                    stosb          ;Store char
                   .if <cx eq 1>
                        mov     bl,'C'
                   .elseif <cx eq 2>
                        mov     bl,':'
                   .elseif <cx eq 3>
                        mov     cl,5       ;make loop stop with error
                   .endif
                 .else
                   mov  cl,5               ;make loop stop with error
                 .endif
               .endif
           .endif
       .else
           mov cl,5                        ;make loop stop with error
       .endif
     .until <bl eq 0> or
     .until <cl a 3>
     .if <cl a 3>
           mov ax,MSG_SYSINIT_INVAL_PARM
           stc
           pop  si
           pop  di
     .endif
     pop  cx
     pop  bx
     ret
EndProc   Config_GetAutoCheck

;
; SUBROUTINE NAME:  Config_GetRom
;
; DESCRIPTIVE NAME:  Get a ROM token
;
; FUNCTION:      To verify and consume a "ROM" token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetRom
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                AX        = token (0=ROM)
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address Rom token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetRom
                push    bx
                lea     bx,DOSINITDATA:RomTable         ;Address the Rom table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetRom


;
; SUBROUTINE NAME:  Config_GetDevType
;
; DESCRIPTIVE NAME:  Get a DevType token
;
; FUNCTION:      To verify and consume a DevType token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetDevType
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;                Carry     Clear
;                AX        = token
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_VerifyToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Address DevType token table
;Verify token (call Config_VerifyToken)
Procedure       Config_GetDevType
                push    bx
                lea     bx,DOSINITDATA:DevTypeTable     ;Address the DevType table
                call    Config_VerifyToken              ;Get and verify the token
                pop     bx
                ret
EndProc         Config_GetDevType


;
; SUBROUTINE NAME:  Config_GetSubType
;
; DESCRIPTIVE NAME:  Get a SubType token
;
; FUNCTION:      To verify and consume a SubType token.
;
; NOTES:
;
; ENTRY POINT:   Config_GetSubType
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;                ES        addresses DOSINITDATA
;
; EXIT-NORMAL:
;
;                Carry     Clear
;                CFG_Token = token
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;                Carry     Set
;                AX        = error code
;                DS:SI     unchanged
;                Token     = invalid token
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;Get a non-delimited token (call Config_GetToken)
;If a token was found
;  If token is longer than 8 characters,
;    Return invalid parameter error
;  Endif
;Endif
Procedure       Config_GetSubType
                xor     ax,ax                           ;Get a non-delimited token
                call    Config_GetToken
                .if     nc                              ;If a token was found
                  push    cx
                  push    di
                  lea     di,DOSINITDATA:CFG_Token      ;  Make sure token is
                  mov     cx,9                          ;  no longer than 8 chars
                  xor     al,al                         ;  (0 trailer in pos 9)
                  repne   scasb
                  .if     nz                            ;  If longer than 8 chars,
                    mov     ax,MSG_SYSINIT_INVAL_PARM   ;    Return invalid parm
                    stc
                  .endif                                ;  Endif
                  pop     di
                  pop     cx
                .endif                                  ;Endif
                ret
EndProc         Config_GetSubType

;
; SUBROUTINE NAME:  Config_GetHexNumber
;
; DESCRIPTIVE NAME:  Get a number token - hex  ;a25207
;
; FUNCTION:      To get and consume a number token in the
;                range 0-(2**32) - 1.
;
; NOTES:
;
; ENTRY POINT:   Config_GetHexNumber
;    LINKAGE:    call near
;
; INPUT:
;
;                DS:SI     -> position to scan for token
;
; EXIT-NORMAL:
;
;                Carry     clear
;                EAX       = number found
;                DS:SI     -> position to scan for next token
;
; EXIT-ERROR:
;
;                Carry     set
;                EAX       = error code (no number or
;                            overflow)
;                Token     = invalid token
;                DS:SI       unchanged
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES:   Config_GetToken
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
;a25207
;     This routine was created to get a hex number
;     token.  The DEVICEHIGH statement previously
;     took decimal values, but this is not consistent
;     with DOS, so Config_wNumber was modified to
;     to convert ascii to hex.
;
;     This process uses 32 bit registers.
;
;Number = 0
;Get token (call Config_GetToken)
;IF no token THEN change to NumberNotFound state
;Get first char of token
;Change to BuildHexNumber state
;
;State BuildHexNumber
;        IF not hexidecimal character THEN change to BadNumberFound state
;        Convert char to binary
;        Number = number * 16 + binary char
;        IF overflow THEN change to BadNumberFound state
;        Get next char
;        IF end of token THEN chage to NumberFound state
;        Repeat
;
;State BadHexNumberFound
;        Set error code
;        Set carry
;        Change to GetHexNumberEnd state
;
;State HexNumberNotFound
;        Set error code
;        Set carry
;        Change to GetHexNumberEnd state
;
;State HexNumberFound
;        Clear carry
;        Change to GetHexNumberEnd state
;
;State GetHexNumberEnd
;        Return

Procedure       Config_GetHexNumber
                assume  ds:nothing,es:DOSINITDATA
                LocalVar   Conversion,BYTE
                EnterProc
state           GetHexNumber

                push    ebx
                push    ds
                push    ecx
                push    edx
                push    si
                xor     ebx,ebx
                mov     bx,16                     ;For hex
                xor     ecx,ecx
                xor     eax,eax                   ;Get a delimited token
                call    Config_GetToken
                push    si
                nextstate HexNumberNotFound c   ;If no token then number not found
                push    es                      ;DS -> DOSINITDATA
                pop     ds
                lea     si,DOSINITDATA:CFG_Token ;DS:SI -> token
                lodsb                           ;Get first char of token
                nextstate BuildHexNumber
endstate        GetNumber

state           BuildHexNumber                     ;Calculate number
                nextstate BadHexNumberFound al <'0','F'> range exclude
                                                ;If char not in range '0'..'F'
                                                ;then the token is bad
                .if     <al be '9'>             ; '0'-'9'
                  sub     eax,'0'               ;Convert hex char to binary
                .elseif <al ae 'A'>             ; 'A'-'F'
                  sub     eax, '7'              ;Convert hex char to binary
                .else
                  nextstate BadHexNumberFound   ;Not hex character
                .endif

                xchg    eax,ecx
                mul     ebx                     ;Number = Number * 16
                add     ecx,eax                 ;Number = Number + digit
                .if     c or                    ;If overflow or
                .if     <nonzero edx>           ;if > 2**32 -1
                  nextstate BadHexNumberFound      ;then number is bad
                .endif
                xor     eax,eax
                lodsb                           ;Get the next char
                nextstate HexNumberFound al 0      ;If end of token then number is found
endstate        BuildHexNumber repeat              ;Repeat

state           BadHexNumberFound                  ;Bad number encountered
                pop     si                      ;Eat recent SI
                pop     si                      ;Restore SI
                mov     ax,MSG_SYSINIT_INVAL_PARM
                stc                             ;Indicate invalid parameter error
                nextstate GetHexNumberEnd
endstate        BadHexNumberFound

state           HexNumberNotFound
                pop     si                      ;Eat recent SI
                pop     si                      ;Restore SI
                mov     ax,MSG_SYSINIT_MISSING_PARM
                stc                             ;Indicate missing parameter error
                nextstate GetHexNumberEnd
endstate        HexNumberNotFound

state           HexNumberFound
                pop     si                      ;Restore SI
                pop     ax                      ;Eat previous SI
                mov     eax,ecx                 ;Return number
                clc                             ;No error
                nextstate GetNumberEnd
endstate        HexNumberFound

state           GetHexNumberEnd
                pop     edx
                pop     ecx
                pop     ds
                pop     ebx
                LeaveProc
                ret
endstate        GetHexNumberEnd
EndProc         Config_GetHexNumber

INITCODE ends
                end
