1implement Unicode; 2 3include "sys.m"; 4sys: Sys; 5 6include "draw.m"; 7 8include "string.m"; 9 str: String; 10 11include "bufio.m"; 12 bufio: Bufio; 13 Iobuf: import bufio; 14 15 16Unicode: module 17{ 18 init: fn(c: ref Draw->Context, v: list of string); 19}; 20 21usage: con "unicode { [-t] hex hex ... | hexmin-hexmax ... | [-n] char ... }"; 22hex: con "0123456789abcdefABCDEF"; 23numout:= 0; 24text:= 0; 25out: ref Bufio->Iobuf; 26stderr: ref sys->FD; 27 28init(nil: ref Draw->Context, argv: list of string) 29{ 30 sys = load Sys Sys->PATH; 31 str = load String String->PATH; 32 bufio = load Bufio Bufio->PATH; 33 34 stderr = sys->fildes(2); 35 36 if(str==nil || bufio==nil){ 37 sys->fprint(stderr, "unicode: can't load String or Bufio module: %r\n"); 38 return; 39 } 40 41 if(argv == nil){ 42 sys->fprint(stderr, "usage: %s\n", usage); 43 return; 44 } 45 argv = tl argv; 46 while(argv != nil) { 47 s := hd argv; 48 if(s != nil && s[0] != '-') 49 break; 50 case s{ 51 "-n" => 52 numout = 1; 53 "-t" => 54 text = 1; 55 } 56 argv = tl argv; 57 } 58 if(argv == nil){ 59 sys->fprint(stderr, "usage: %s\n", usage); 60 return; 61 } 62 63 out = bufio->fopen(sys->fildes(1), Bufio->OWRITE); 64 65 if(!numout && oneof(hd argv, '-')) 66 range(argv); 67 else if(numout || oneof(hex, (hd argv)[0]) == 0) 68 nums(argv); 69 else 70 chars(argv); 71 out.flush(); 72} 73 74oneof(s: string, c: int): int 75{ 76 for(i:=0; i<len s; i++) 77 if(s[i] == c) 78 return 1; 79 return 0; 80} 81 82badrange(q: string) 83{ 84 sys->fprint(stderr, "unicode: bad range %s\n", q); 85} 86 87range(argv: list of string) 88{ 89 min, max: int; 90 91 while(argv != nil){ 92 q := hd argv; 93 if(oneof(hex, q[0]) == 0){ 94 badrange(q); 95 return; 96 } 97 (min, q) = str->toint(q,16); 98 if(min<0 || min>Sys->Runemax || len q==0 || q[0]!='-'){ 99 badrange(hd argv); 100 return; 101 } 102 q = q[1:]; 103 if(oneof(hex, q[0]) == 0){ 104 badrange(hd argv); 105 return; 106 } 107 (max, q) = str->toint(q,16); 108 if(max<0 || max>Sys->Runemax || max<min || len q>0){ 109 badrange(hd argv); 110 return; 111 } 112 i := 0; 113 do{ 114 out.puts(sys->sprint("%.4x %c", min, min)); 115 i++; 116 if(min==max || (i&7)==0) 117 out.puts("\n"); 118 else 119 out.puts("\t"); 120 min++; 121 }while(min<=max); 122 argv = tl argv; 123 } 124} 125 126 127nums(argv: list of string) 128{ 129 while(argv != nil){ 130 q := hd argv; 131 for(i:=0; i<len q; i++) 132 out.puts(sys->sprint("%.4x\n", q[i])); 133 argv = tl argv; 134 } 135} 136 137badvalue(s: string) 138{ 139 sys->fprint(stderr, "unicode: bad unicode value %s\n", s); 140} 141 142chars(argv: list of string) 143{ 144 m: int; 145 146 while(argv != nil){ 147 q := hd argv; 148 if(oneof(hex, q[0]) == 0){ 149 badvalue(hd argv); 150 return; 151 } 152 (m, q) = str->toint(q, 16); 153 if(m<0 || m>Sys->Runemax || len q>0){ 154 badvalue(hd argv); 155 return; 156 } 157 out.puts(sys->sprint("%c", m)); 158 if(!text) 159 out.puts("\n"); 160 argv = tl argv; 161 } 162} 163