home *** CD-ROM | disk | FTP | other *** search
- /* -------------------------------------------------------
- *** Template for Procedure Heading ***
-
- Name:
- Result:
- Errors:
- Globals:
- Macros:
- Procedures:
-
- Action:
-
- ------------------------------------------------------- */
-
- /* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
-
- ucsd2cpm -- Transfer '.TEXT' files from a UCSD directory
- formatted disk to a CP/M directory formatted
- disk.
-
- 1) header blocks removed
- 2) linefeeds added after carriage returns
- 3) indents converted to appropriate # of spaces
- 4) filler nulls removed
- 5) control-A's removed (added 2/13/80 hrm)
-
- : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
-
-
-
-
-
- /* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
-
- Constants
-
- : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
-
-
- #define DLE 0x10 /* Data Link Escape -- indent flag */
- #define CR 0x0D /* carriage return */
- #define LF 0x0A /* linefeed */
- #define NULL 0 /* ascii null */
- #define CPM_EOF 0X1A /* CP/M ascii endfile mark */
-
- #define TRUE 1 /* booleans */
- #define FALSE 0
-
- #define SEL_DSK 14 /* bdos function number */
- #define SET_DMA 26 /* bdos function number */
-
- #define SET_TRK 9 /* bios index number */
- #define SET_SEC 10 /* bios index number */
- #define READ 12 /* bios index number */
-
- #define DUMMY 0 /* dummy parameter for bios routine */
-
- #define EOF_F 0xFFFF /* end of file flag */
- #define D_ENT_SZ 26 /* UCSD directory entry size */
- #define D_TITLE 6 /* offset to entry title */
- #define UCSD_NAM_SZ 20 /* size of the name part of ucsd dir entry */
- #define UCSD_DIR_SZ 2048 /* size of UCSD directory in bytes */
-
- #define SECT_SIZE 128 /* bytes per physical sector */
- #define BLOK_SIZE 512 /* bytes per UCSD logical block */
- #define SECT_PER_BLOK 4 /* physical sectors per logical block */
-
-
-
-
- /* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
-
- Globals -- these would be static if it were available
-
- : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
-
- int lsn; /* logical sector number */
- int lstlsn; /* last logical sector number */
- int nbytes; /* number of bytes remaining in ucsd file buffer */
- char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd file */
- char *ptr; /* pointer to current byte in ucsd file buffer */
-
-
-
-
- /* : : : : : : : : : : : : : : : : : : : : : : : : : : : :
-
- Global structure type
-
- : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
-
- struct buf {
- int fd;
- int nleft;
- char *nextp;
- char buff[SECT_SIZE];
- };
-
- /* -------------------------------------------------------
-
- Name: main(argc,argv)
- Result: ---
- Errors: invocation syntax
- Globals: lsn,lstlsn,nbytes,ptr,ucsdbuf
- Macros: CPM_FILE,UCSD_FILE,UCSD_NAM_SZ
-
- Procedures: puts(),exit(),force_upr(),printf()
- putchar(),close(),unlink(),strcpy()
- strcat(),getchar(),open(),copy()
- tolower()
-
- Action: Call copy() to copy a '.TEXT' file
- from a UCSD formatted disk in drive B
- to a user specified file name in
- drive A
-
- Handle invocation errors
- Handle case of already existing
- destination file
-
- ------------------------------------------------------- */
-
- #define CPM_FILE argv[1]
- #define UCSD_FILE argv[2]
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int file_id;
- char ucsdname[UCSD_NAM_SZ];
-
- lsn = lstlsn = nbytes = 0; /* init globals */
- ptr = ucsdbuf;
-
- if( argc != 3 ) {
- puts("Proper invocation form is:\n\n");
- puts("UCSD2CPM <cpm-file-name> <ucsd-file-name>\n");
- puts("This copies B:<ucsd-file-name>.TEXT to A:<cpm-file-name>\n");
- exit(1);
- }
- force_upr(UCSD_FILE); /* make <ucsd-file-name> upper case */
- if( (file_id = open(CPM_FILE,0)) >= 0 ) {
- printf("%s already exists. Delete it ? ",CPM_FILE);
- if( tolower(getchar()) != 'y' ) {
- puts("\naborted\n");
- exit(1);
- }
- putchar('\n');
- close(file_id);
- unlink(CPM_FILE);
- }
- else
- close(file_id);
- strcpy(ucsdname,UCSD_FILE);
- strcat(ucsdname,".TEXT");
- if(copy(ucsdname,CPM_FILE))
- printf("\n\nno such file %s .. aborted\n",ucsdname);
- exit(0);
- }
-
- /* -------------------------------------------------------
-
- Name: copy (ucsd_file,cpm_file)
- Result: TRUE if error , FALSE if transfer ok
-
- Errors: no such '.TEXT' file
-
- Globals: struct buf,
- Macros: TRUE,EOF_F,CR,DLE,NULL,CPM_EOF,FALSE
-
- Procedures: find_file(),fcreat(),getbyte()
- putc(),fflush(),fclose()
-
- Action: Find '.TEXT' file in UCSD directory
- on drive B
- Create user specified file on
- drive A
- copy file content from UCSD to CP/M
- car by char translating:
- Skip header block
- Ignore NULL's
- Add LF after CR
- Convert DLE <count> to
- appropriate number of spaces
- close output file
-
- ------------------------------------------------------- */
-
- copy(ucsd_file,cpm_file)
- char *ucsd_file,*cpm_file;
- {
- struct buf tofile;
- int c;
-
- if( ! find_file(ucsd_file) ) /* no such file */
- return TRUE;
- fcreat(cpm_file,&tofile);
- while( (c = getbyte()) != EOF_F )
- switch(c) {
-
- case CR: putc(CR,&tofile); /* LF after CR */
- putc(LF,&tofile);
- break;
-
- case DLE: for( c = (getbyte() - 32); c; c-- )
- putc(' ',&tofile); /* fill spaces */
- break;
-
- case '\1': /* ignore ^A's */
- case NULL: break; /* ignore nulls */
-
- default: putc(c,&tofile); /* pass char unmodified */
- break;
- }
- putc(CPM_EOF,&tofile); /* send cp/m ascii endfile */
- fflush(&tofile);
- fclose(&tofile);
- return FALSE; /* signal transfer ok */
- }
-
- /* -------------------------------------------------------
-
- Name: getbyte()
- Result: next sequential byte from UCSD '.TEXT' file
- Errors:
- Globals: lsn,lstlsn,nbytes,ptr,ucsdbuf[]
- Macros: EOF_F,BLOK_SIZE,SECT_PER_BLOK
- Procedures: read_ucsd()
-
- Action: read block at a time
- pass along byte at a time
- return EOF_F if end of UCSD file
-
- ------------------------------------------------------- */
-
-
- getbyte()
- {
- if( lsn > lstlsn)
- return EOF_F;
- if( nbytes-- )
- return *ptr++;
- read_ucsd(ucsdbuf,lsn,1);
- nbytes = (BLOK_SIZE-1);
- ptr = ucsdbuf;
- lsn += SECT_PER_BLOK;
- return *ptr++;
- }
-
-
- /* -------------------------------------------------------
-
- Name: fclose(file)
- Result: status of closing action
- Errors: ---
- Globals: struct buf
- Macros: ---
- Procedures: close()
-
- Action: file open for buffered input
- or output is closed
-
- ------------------------------------------------------- */
-
-
- fclose(file)
- struct buf *file;
- {
- return close( file->fd );
- }
-
- /* -------------------------------------------------------
-
- Name: find_file(ucsd_name)
- Result: TRUE if found, FALSE if not found
- Errors:
- Globals: lsn,lstlsn
- Macros: D_ENT_SZ,SECT_PER_BLOK,D_TITLE
- TRUE,FALSE,UCSD_DIR_SZ
-
- Procedures: read_ucsd()
-
- Action: ---
-
- ------------------------------------------------------- */
-
-
- find_file(ucsd_name)
- char *ucsd_name;
- {
- char ucsd_dir[UCSD_DIR_SZ];
- char *dir,*saved_dir,*name;
- int name_len;
-
- name = ucsd_name;
- read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4);
- dir = &ucsd_dir[D_TITLE + D_ENT_SZ]; /* skip title block */
- while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) {
- saved_dir = dir;
- if( (name_len = *dir++) <=0 || name_len > 19 )
- return FALSE;
- while( *dir++ == *name++ ) {
- if( --name_len ) /* continue comparison check */
- ;
- else { /* entry found */
- dir = saved_dir - D_TITLE; /* point to alloc. info. */
- lsn = *dir++;
- lsn += *dir++ << 8; /* lsn = starting logical block number */
- lsn += 2; /* bypass header blocks */
- lsn *= SECT_PER_BLOK; /* 1'st logical sector number */
-
- lstlsn = *dir++;
- lstlsn += *dir++ << 8; /* lstlsn = ending logical block # */
- lstlsn *= SECT_PER_BLOK; /* lstlsn = last logical sector # */
- return TRUE; /* indicate file found */
- }
- }
- name = ucsd_name; /* reset comparison name pointer */
- dir = saved_dir + D_ENT_SZ; /* point at next entry name */
- }
- return FALSE; /* no such file */
- }
-
- /* -------------------------------------------------------
-
- Name: read_ucsd()
- Result: status of selecting drive A
- Errors: sector read error
- Globals: ---
- Macros: SEL_DSK,SET_DMA,SET_TRK,SET_SEC
- READ,DUMMY,SECT_SIZE
- Procedures: bios(),bdos(),printf(),exit()
-
- Action: Read count blocks from drive B
- into buf starting at UCSD logical
- record number rn
-
- ------------------------------------------------------- */
-
-
- read_ucsd(buf,rn,count)
- char *buf;
- unsigned rn;
- int count;
- {
- char bios();
- int seccnt; seccnt = count*4;
-
- bdos(SEL_DSK,1);
- while( seccnt-- ) {
- bdos(SET_DMA,buf);
- bios(SET_TRK,track(rn));
- bios(SET_SEC,sector(rn));
- if( bios(READ,DUMMY) ) {
- printf("read error @ track %2d sector %2d",track(rn),sector(rn));
- exit(1);
- }
- buf += SECT_SIZE;
- rn++;
- }
- return bdos(SEL_DSK,0);
- }
-
- /* -------------------------------------------------------
-
- Name: sector(rn)
- Result: absolute sector number
- Errors: ---
- Globals: ---
- Macros: ---
- Procedures: ---
-
- Action: convert logical record number
- to absolute sector
-
- maps logical records to physical sectors
- by selecting every second sector in order
- (accounting for the modulo 26 process)
- on the diskette except that at a track
- switchover point there is an additional
- 'gap' of 6 sectors (total of 7) to allow
- for the drive to seek. This is UCSD's
- attempt to minimize disk access time.
-
- ------------------------------------------------------- */
-
- sector(rn)
- unsigned rn;
- {
- unsigned t1,t2,trk,t3,sect;
-
- t1 = rn % 26;
- t2 = t1 << 1;
- if(t1 > 12)
- t2++;
- trk = rn/26; /* zero based absolute track */
- t3 = t2 + 6*trk; /* new logical sector number */
- sect = t3 % 26; /* new zero based absolute sector */
- return ++sect; /* one based absolute sector */
- }
-
- /* -------------------------------------------------------
-
- Name: track(rn)
- Result: absolute track number
- Errors: ---
- Globals: ---
- Macros: ---
- Procedures: ---
-
- Action: convert logical sector number to
- absolute track This is simply the modulo
- 26 process except that track 0 is not
- considered part of the logical
- sector space.
-
- ------------------------------------------------------- */
-
-
- track(rn)
- unsigned rn;
- {
- return rn/26 + 1;
- }
-
- /* -------------------------------------------------------
-
- Name: index(str,sstr)
- Result: position of string sstr in string str
- -1 if not a substring
- Errors: ---
- Globals: ---
- Macros: ---
- Procedures: ---
-
- Action: ---
-
- ------------------------------------------------------- */
-
-
- index(str,sstr)
- char *str,*sstr;
- {
- int first_match;
-
- if( *sstr == 0 ) /* null string is a substring of all strings */
- return 0;
- for( first_match=0; *str != *sstr; first_match++)
- if( *str == 0 )
- return -1;
- else
- str++;
- while( *sstr )
- if( *str++ != *sstr++ )
- return -1;
- return first_match;
- }
-
- /* -------------------------------------------------------
-
- Name: force_upr(string)
- Result: ---
- Errors: ---
- Globals: ---
- Macros: ---
- Procedures: ---
-
- Action: force each char of string to upper case
-
- ------------------------------------------------------- */
-
- force_upr(string)
- char *string;
- {
- while(*string)
- *string = *string++;
- return;
- }
-
- /* -------------------------------------------------------
-
- Name: print(string,n)
- Result: ---
- Errors: ---
- Globals: ---
- Macros: ---
- Procedures: putchar()
-
- Action: print n chars to console starting
- at char pointer string
-
- ------------------------------------------------------- */
-
- print(string,n)
- char *string;
- int n;
- {
- while(n--)
- putchar(*string++);
- return;
- }
-