$include (..\lib\compStch.ext) /* *============================================================================ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ fileAttributeModule: do; $if not noID declare IDString (*) byte data ( '@(#)fattrib.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $include (..\lib\comnDefs.ext) $set (fileAttributesSource) $include (..\lib\dirFunct.ext) $include (..\lib\sysCalls.ext) $include (..\lib\string.ext) attrib: procedure ( pathString, flagStringPtr, returnAttributesPtr ) word reentrant public; declare pathString pointer, flagStringPtr pointer, flagString based flagStringPtr (*) char, returnAttributesPtr pointer, returnedAttributes based returnAttributesPtr word, flagIndex word, flagChar char, returnCode word; declare attribute_t literally 'byte', noModify literally '0', clearAttribute literally '1', setAttribute literally '2', /* * this array corresponds to the order of the bits in the bitfield * returned by the DOS call ... indeed this won't work if it does * not match */ attributeChars (*) char data ( 'R', 'H', 'S', 0, 0, 'A' ), /* [rhs a] */ NUMBER_ATTRIBUTES literally '6'; /* size( attributeChars ) */ declare attributeMasks ( NUMBER_ATTRIBUTES ) attribute_t, modifyAttribute char, attributeIndex integer; /* * initialize the return indication, and the attribute indicators */ returnCode = 0; call setb( noModify, @attributeMasks, size( attributeMasks ) ); /* * parse the attribute format string */ flagIndex = 0; do while ( ( flagChar := flagString( flagIndex ) ) <> NUL ); /* * we have something to process if this is not a whitespace. save the modifier and * point to the next character in the flag string */ if ( flagChar <> ' ' ) then do; modifyAttribute = flagChar; flagIndex = flagIndex + 1; flagChar = toupper( flagString( flagIndex ) ); /* * the flag character is now one of [RHSA]. if not, don't do anything */ attributeIndex = signed( findb( @attributeChars, flagChar, size( attributeChars ) ) ); if ( attributeIndex >= 0 ) then if ( modifyAttribute = '-' ) then attributeMasks( attributeIndex ) = clearAttribute; else if ( modifyAttribute = '+' ) then attributeMasks( attributeIndex ) = setAttribute; end; flagIndex = flagIndex + 1; end; /* parsing the flagString */ /* * now, get the attributes of the file specified, modify them, and write them back */ manageAttributeCommands: do; declare cpuRegisters; wordRegs.Ax = 4300h; /* get a file's attributes */ wordRegs.Ds = selector$of( pathString ); wordRegs.Dx = offset$of( pathString ); call int86( DOS_CALL, @wordRegs ); if ( not carryClear( @wordRegs ) ) then do; returnCode = wordRegs.Ax; end; else do; returnedAttributes = wordRegs.Cx; /* * now that we have the attributes, decide what we need to modify * and get after it */ do attributeIndex = 0 to ( NUMBER_ATTRIBUTES - 1 ); do case attributeMasks( attributeIndex ); /* noModify */ do; end; /* clear */ do; returnedAttributes = returnedAttributes and ( not ( shl( 1, byte( attributeIndex ) ) ) ); end; /* set */ do; returnedAttributes = returnedAttributes or ( shl( 1, byte( attributeIndex ) ) ); end; end; end; /* * we have the mask, so write it back */ wordRegs.Ax = 4301h; wordRegs.Cx = returnedAttributes; call int86( DOS_CALL, @wordRegs ); if ( not carryClear( @wordRegs ) ) then returnCode = wordRegs.Ax; end; end manageAttributeCommands; return ( returnCode ); end attrib; end fileAttributeModule;