home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol144 / ucsdtype.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  14.3 KB  |  454 lines

  1. /*      ------------------------------------------------------- 
  2.         *** Template for Procedure Heading *** 
  3.  
  4.         Name: 
  5.         Result: 
  6.         Errors: 
  7.         Globals: 
  8.         Macros: 
  9.         Procedures: 
  10.  
  11.         Action: 
  12.  
  13.         ------------------------------------------------------- */ 
  14.  
  15. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  16.  
  17.         ucsdtype -- Transfer '.TEXT' files from a UCSD directory 
  18.             to cp/m console device.
  19.  
  20.          -- Based upon the program UCSD2CPM.
  21.             Kludged by Chris Undery
  22.             11 Margaret St, Newtown
  23.             Sydney, Australia 2042
  24.  
  25.            
  26.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  27.  
  28.  
  29.  
  30.  
  31.  
  32. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  33.  
  34.                 Constants 
  35.  
  36.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  37.  
  38. #include bdscio.h
  39.  
  40. #define DLE     0x10            /* Data Link Escape -- indent flag */ 
  41. #define CR      0x0D            /* carriage return */ 
  42. #define LF      0x0A            /* linefeed */ 
  43. #define NULL    0               /* ascii null */ 
  44. #define CPM_EOF 0X1A            /* CP/M ascii endfile mark */ 
  45.  
  46. #define TRUE    1               /* booleans */ 
  47. #define FALSE   0 
  48.  
  49. #define SEL_DSK 14              /* bdos function number */ 
  50. #define SET_DMA 26              /* bdos function number */ 
  51.  
  52. #define SET_TRK 10              /* bios index number (was 9 c.u.) */ 
  53. #define SET_SEC 11              /* bios index number (was 10 c.u) */ 
  54. #define READ    13              /* bios index number (was 12 c.u) */ 
  55.  
  56. #define DUMMY   0               /* dummy parameter for bios routine */ 
  57.  
  58. #define EOF_F   0xFFFF          /* end of file flag */ 
  59. #define D_ENT_SZ 26             /* UCSD directory entry size */ 
  60. #define D_TITLE 6               /* offset to entry title */ 
  61. #define UCSD_NAM_SZ 20          /* size of the name part of ucsd dir entry */ 
  62. #define UCSD_DIR_SZ 2048        /* size of UCSD directory in bytes */ 
  63.  
  64. #define SECT_SIZE 128           /* bytes per physical sector */ 
  65. #define BLOK_SIZE 512           /* bytes per UCSD logical block */ 
  66. #define SECT_PER_BLOK 4         /* physical sectors per logical block */ 
  67.  
  68.  
  69.  
  70.  
  71. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  72.  
  73.         Globals -- these would be static if it were available 
  74.  
  75.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  76.  
  77. int lsn;                /* logical sector number */ 
  78. int lstlsn;             /* last logical sector number */ 
  79. int nbytes;             /* number of bytes remaining in ucsd file buffer */ 
  80. char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd file */ 
  81. char *ptr;              /* pointer to current byte in ucsd file buffer */ 
  82. char tofile[BUFSIZ];    /* cp/m destination file buffer */ 
  83.  
  84.  
  85.  
  86.  
  87.  
  88. /*     ------------------------------------------------------- 
  89.  
  90.         Name:           main(argc,argv) 
  91.         Result:         --- 
  92.         Errors:         invocation syntax 
  93.         Globals:        lsn,lstlsn,nbytes,ptr,ucsdbuf 
  94.         Macros:         CPM_FILE,UCSD_FILE,UCSD_NAM_SZ 
  95.  
  96.         Procedures:     puts(),exit(),force_upr(),printf() 
  97.                         putchar(),close(),unlink(),strcpy() 
  98.                         strcat(),getchar(),open(),copy() 
  99.                         tolower() 
  100.  
  101.         Action:         Call copy() to copy a '.TEXT' file 
  102.                         from a UCSD formatted disk in drive B 
  103.                         to a user specified file name in 
  104.                         drive A 
  105.  
  106.                         Handle invocation errors 
  107.                         Handle case of already existing 
  108.                         destination  file 
  109.  
  110.         ------------------------------------------------------- */ 
  111.  
  112. #define UCSD_FILE argv[1] 
  113.  
  114. main(argc,argv) 
  115.         int argc; 
  116.         char *argv[]; 
  117.         { 
  118.         int file_id; 
  119.         char ucsdname[UCSD_NAM_SZ]; 
  120.  
  121.         lsn = lstlsn = nbytes = 0;      /* init globals */ 
  122.         ptr = ucsdbuf; 
  123.  
  124.         if( argc != 2 ) { 
  125.           puts("Proper invocation form is:\n\n"); 
  126.           puts("UCSDTYPE <ucsd_name> (implied.TEXT)\n");
  127.           exit(1); 
  128.           } 
  129.         force_upr(UCSD_FILE);   /* make <ucsd-file-name> upper case */ 
  130.         strcpy(ucsdname,UCSD_FILE); 
  131.         strcat(ucsdname,".TEXT"); 
  132.         if(copy(ucsdname,"phooey")) 
  133.           printf("\n\nno such file %s .. aborted\n",ucsdname); 
  134.         exit(0); 
  135.         } 
  136.  
  137. /*     ------------------------------------------------------- 
  138.  
  139.         Name:           copy (ucsd_file,cpm_file) 
  140.         Result:         TRUE if error , FALSE if transfer ok 
  141.  
  142.         Errors:         no such '.TEXT' file 
  143.  
  144.         Globals:        struct buf, 
  145.         Macros:         TRUE,EOF_F,CR,DLE,NULL,CPM_EOF,FALSE 
  146.  
  147.         Procedures:     find_file(),fcreat(),getbyte() 
  148.                         putc(),fflush(),fclose() 
  149.  
  150.         Action:         Find '.TEXT' file in UCSD directory 
  151.                         on drive B 
  152.                         Create user specified file on 
  153.                         drive A 
  154.                         copy file content from UCSD to CP/M 
  155.                         car by char translating: 
  156.                                 Skip header block 
  157.                                 Ignore NULL's 
  158.                                 Add LF after CR 
  159.                                 Convert DLE <count> to 
  160.                                 appropriate number of spaces 
  161.                         close output file 
  162.  
  163.         ------------------------------------------------------- */ 
  164.  
  165. copy(ucsd_file,cpm_file) 
  166.         char *ucsd_file,*cpm_file; 
  167.         { 
  168.  
  169.         int c; 
  170.  
  171.         if( ! find_file(ucsd_file) )            /* no such file */ 
  172.           return TRUE; 
  173.         while( (c = getbyte()) != EOF_F ) 
  174.           switch(c) { 
  175.  
  176.             case CR:    putchar(CR);       /* LF after CR */ 
  177.                         putchar(LF); 
  178.                         break; 
  179.  
  180.             case DLE:   for( c = (getbyte() - 32); c; c-- ) 
  181.                           putchar(' ');    /* fill spaces */ 
  182.                         break; 
  183.  
  184.             case '\1':                          /* ignore ^A's */ 
  185.             case NULL:  break;                  /* ignore nulls */ 
  186.  
  187.             default:    putchar(c);        /* pass char unmodified */ 
  188.                         break; 
  189.             } 
  190.        puts("** end of UCSD file **\n");
  191.         return FALSE;                           /* signal transfer ok */ 
  192.         } 
  193.  
  194. /*     ------------------------------------------------------- 
  195.  
  196.         Name:           getbyte() 
  197.         Result:         next sequential byte from UCSD '.TEXT' file 
  198.         Errors: 
  199.         Globals:        lsn,lstlsn,nbytes,ptr,ucsdbuf[] 
  200.         Macros:         EOF_F,BLOK_SIZE,SECT_PER_BLOK 
  201.         Procedures:     read_ucsd() 
  202.  
  203.         Action:         read block at a time 
  204.                         pass along byte at a time 
  205.                         return EOF_F if end of UCSD file 
  206.  
  207.         ------------------------------------------------------- */ 
  208.  
  209.  
  210. getbyte() 
  211.         { 
  212.         if( lsn > lstlsn) 
  213.           return EOF_F; 
  214.         if( nbytes-- ) 
  215.           return *ptr++; 
  216.         read_ucsd(ucsdbuf,lsn,1); 
  217.         nbytes = (BLOK_SIZE-1); 
  218.         ptr = ucsdbuf; 
  219.         lsn += SECT_PER_BLOK; 
  220.         return *ptr++; 
  221.         } 
  222.  
  223.  
  224. /*     ------------------------------------------------------- 
  225.  
  226.         Name:           find_file(ucsd_name) 
  227.         Result:         TRUE if found, FALSE if not found 
  228.         Errors: 
  229.         Globals:        lsn,lstlsn 
  230.         Macros:         D_ENT_SZ,SECT_PER_BLOK,D_TITLE 
  231.                         TRUE,FALSE,UCSD_DIR_SZ 
  232.  
  233.         Procedures:     read_ucsd() 
  234.  
  235.         Action:         --- 
  236.  
  237.         ------------------------------------------------------- */ 
  238.  
  239.  
  240. find_file(ucsd_name) 
  241.         char *ucsd_name; 
  242.         { 
  243.         char ucsd_dir[UCSD_DIR_SZ]; 
  244.         char *dir,*saved_dir,*name; 
  245.         int name_len; 
  246.  
  247.         name = ucsd_name; 
  248.         read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4); 
  249.         dir = &ucsd_dir[D_TITLE + D_ENT_SZ];    /* skip title block */ 
  250.         while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) { 
  251.           saved_dir = dir; 
  252.           if( (name_len = *dir++) <=0 || name_len > 19 ) 
  253.             return FALSE; 
  254.           while( *dir++ == *name++ ) { 
  255.             if( --name_len )    /* continue comparison check */ 
  256.               ; 
  257.             else {                              /* entry found */ 
  258.               dir = saved_dir - D_TITLE;        /* point to alloc. info. */ 
  259.               lsn = *dir++; 
  260.               lsn += *dir++ << 8;   /* lsn = starting logical block number */ 
  261.               lsn += 2;             /* bypass header blocks */ 
  262.               lsn *= SECT_PER_BLOK; /* 1'st logical sector number */ 
  263.  
  264.               lstlsn = *dir++; 
  265.               lstlsn += *dir++ << 8;    /* lstlsn = ending logical block # */ 
  266.               lstlsn *= SECT_PER_BLOK;  /* lstlsn = last logical sector # */ 
  267.               return TRUE;              /* indicate file found */ 
  268.               } 
  269.             } 
  270.           name = ucsd_name;             /* reset comparison name pointer */ 
  271.           dir = saved_dir + D_ENT_SZ;   /* point at next entry name */ 
  272.           } 
  273.         return FALSE;                           /* no such file */ 
  274.         } 
  275.  
  276. /*     ------------------------------------------------------- 
  277.  
  278.         Name:           read_ucsd() 
  279.         Result:         status of selecting drive A 
  280.         Errors:         sector read error 
  281.         Globals:        --- 
  282.         Macros:         SEL_DSK,SET_DMA,SET_TRK,SET_SEC 
  283.                         READ,DUMMY,SECT_SIZE 
  284.         Procedures:     bios(),bdos(),printf(),exit() 
  285.  
  286.         Action:         Read count blocks from drive B 
  287.                         into buf starting at UCSD logical 
  288.                         record number rn 
  289.  
  290.         ------------------------------------------------------- */ 
  291.  
  292.  
  293. read_ucsd(buf,rn,count) 
  294.         char *buf; 
  295.         unsigned rn; 
  296.         int count; 
  297.         { 
  298.         char bios(); 
  299.         int seccnt; seccnt = count*4; 
  300.  
  301.         bdos(SEL_DSK,1); 
  302.         while( seccnt-- ) { 
  303.           bdos(SET_DMA,buf); 
  304.           bios(SET_TRK,track(rn)); 
  305.           bios(SET_SEC,sector(rn)); 
  306.           if( bios(READ,DUMMY) ) { 
  307.             printf("read error @ track %2d sector %2d",track(rn),sector(rn)); 
  308.             exit(1); 
  309.             } 
  310.           buf += SECT_SIZE; 
  311.           rn++; 
  312.           } 
  313.         return bdos(SEL_DSK,0); 
  314.         } 
  315.  
  316. /*     ------------------------------------------------------- 
  317.  
  318.         Name:           sector(rn) 
  319.         Result:         absolute sector number 
  320.         Errors:         --- 
  321.         Globals:        --- 
  322.         Macros:         --- 
  323.         Procedures:     --- 
  324.  
  325.         Action:         convert logical record number 
  326.                         to absolute sector 
  327.  
  328.                         maps logical records to physical sectors 
  329.                         by selecting every second sector in order 
  330.                         (accounting for the modulo 26 process) 
  331.                         on the diskette except that at a track 
  332.                         switchover point there is an additional 
  333.                         'gap' of 6 sectors (total of 7) to allow 
  334.                         for the drive to seek. This is UCSD's 
  335.                         attempt to minimize disk access time. 
  336.  
  337.         ------------------------------------------------------- */ 
  338.  
  339. sector(rn) 
  340.         unsigned rn; 
  341.         { 
  342.         unsigned t1,t2,trk,t3,sect; 
  343.  
  344.         t1 = rn % 26; 
  345.         t2 = t1 << 1; 
  346.         if(t1 > 12) 
  347.           t2++; 
  348.         trk = rn/26;            /* zero based absolute track */ 
  349.         t3 = t2 + 6*trk;        /* new logical sector number */ 
  350.         sect = t3 % 26;         /* new zero based absolute sector */ 
  351.         return ++sect;          /* one based absolute sector */ 
  352.         } 
  353.  
  354. /*      ------------------------------------------------------- 
  355.  
  356.         Name:           track(rn) 
  357.         Result:         absolute track number 
  358.         Errors:         --- 
  359.         Globals:        --- 
  360.         Macros:         --- 
  361.         Procedures:     --- 
  362.  
  363.         Action:         convert logical sector number to 
  364.                         absolute track This is simply the modulo 
  365.                         26 process except that track 0 is not 
  366.                         considered part of the logical 
  367.                         sector space. 
  368.  
  369.         ------------------------------------------------------- */ 
  370.  
  371.  
  372. track(rn) 
  373.         unsigned rn; 
  374.         { 
  375.         return rn/26 + 1; 
  376.         } 
  377.  
  378. /*     ------------------------------------------------------- 
  379.  
  380.         Name:           index(str,sstr) 
  381.         Result:         position of string sstr in string str 
  382.                         -1 if not a substring 
  383.         Errors:         --- 
  384.         Globals:        --- 
  385.         Macros:         --- 
  386.         Procedures:     --- 
  387.  
  388.         Action:         --- 
  389.  
  390.         ------------------------------------------------------- */ 
  391.  
  392.  
  393. index(str,sstr) 
  394.         char *str,*sstr; 
  395.         { 
  396.         int first_match; 
  397.  
  398.         if( *sstr == 0 )  /* null string is a substring of all strings */ 
  399.           return 0; 
  400.         for( first_match=0; *str != *sstr; first_match++) 
  401.           if( *str == 0 ) 
  402.             return -1; 
  403.           else 
  404.             str++; 
  405.         while( *sstr ) 
  406.           if( *str++ != *sstr++ ) 
  407.             return -1; 
  408.         return first_match; 
  409.         } 
  410.  
  411. /*      ------------------------------------------------------- 
  412.  
  413.         Name:           force_upr(string) 
  414.         Result:         --- 
  415.         Errors:         --- 
  416.         Globals:        --- 
  417.         Macros:         --- 
  418.         Procedures:     --- 
  419.  
  420.         Action:         force each char of string to upper case 
  421.  
  422.         ------------------------------------------------------- */ 
  423.  
  424. force_upr(string) 
  425.         char *string; 
  426.         { 
  427.         while(*string) 
  428.           *string = *string++; 
  429.         return; 
  430.         } 
  431.  
  432. /*      ------------------------------------------------------- 
  433.  
  434.         Name:           print(string,n) 
  435.         Result:         --- 
  436.         Errors:         --- 
  437.         Globals:        --- 
  438.         Macros:         --- 
  439.         Procedures:     putchar() 
  440.  
  441.         Action:         print n chars to console starting 
  442.                         at char pointer string 
  443.  
  444.         ------------------------------------------------------- */ 
  445.  
  446. print(string,n) 
  447.         char *string; 
  448.         int n; 
  449.         { 
  450.         while(n--) 
  451.           putchar(*string++); 
  452.         return; 
  453.         } 
  454.