CTC++ Coverage Report - Execution Profile    #339/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/char/consolemap.c
Instrumentation mode: function-decision-multicondition
TER: 46 % (142/311)

Start/ End/    
True False - Line Source

  1 /*
  2  * consolemap.c
  3  *
  4  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
  5  * to font positions.
  6  *
  7  * aeb, 950210
  8  *
  9  * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
  10  *
  11  * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
  12  */
  13 
  14 #include <linux/config.h>
  15 #include <linux/module.h>
  16 #include <linux/kd.h>
  17 #include <linux/errno.h>
  18 #include <linux/mm.h>
  19 #include <linux/slab.h>
  20 #include <linux/init.h>
  21 #include <linux/tty.h>
  22 #include <asm/uaccess.h>
  23 #include <linux/consolemap.h>
  24 #include <linux/vt_kern.h>
  25 
  26 static unsigned short translations[][256] = {
  27   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
  28   {
  29     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  30     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  31     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  32     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  33     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  34     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  35     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  36     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  37     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  38     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  39     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  40     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  41     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  42     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  43     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  44     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  45     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  46     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  47     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  48     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  49     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  50     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  51     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  52     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  53     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  54     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  55     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  56     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  57     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  58     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  59     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  60     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  61   }, 
  62   /* VT100 graphics mapped to Unicode */
  63   {
  64     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  65     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  66     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  67     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  68     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  69     0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
  70     0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  71     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  72     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  73     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  74     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  75     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
  76     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
  77     0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
  78     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
  79     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
  80     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  81     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  82     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  83     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  84     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  85     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  86     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  87     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  88     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  89     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  90     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  91     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  92     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  93     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  94     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  95     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  96   },
  97   /* IBM Codepage 437 mapped to Unicode */
  98   {
  99     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
  100     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
  101     0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
  102     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
  103     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  104     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  105     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  106     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  107     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  108     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  109     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  110     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  111     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  112     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  113     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  114     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
  115     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
  116     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
  117     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
  118     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
  119     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
  120     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
  121     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
  122     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
  123     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
  124     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
  125     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
  126     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
  127     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
  128     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
  129     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
  130     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
  131   }, 
  132   /* User mapping -- default to codes for direct font mapping */
  133   {
  134     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
  135     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
  136     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
  137     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
  138     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
  139     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
  140     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
  141     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
  142     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
  143     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
  144     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
  145     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
  146     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
  147     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
  148     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
  149     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
  150     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
  151     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
  152     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
  153     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
  154     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
  155     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
  156     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
  157     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
  158     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
  159     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
  160     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
  161     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
  162     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
  163     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
  164     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
  165     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
  166   }
  167 };
  168 
  169 /* The standard kernel character-to-font mappings are not invertible
  170    -- this is just a best effort. */
  171 
  172 #define MAX_GLYPH 512      /* Max possible glyph value */
  173 
  174 static int inv_translate[MAX_NR_CONSOLES];
  175 
  176 struct uni_pagedir {
  177    u16       **uni_pgdir[32];
  178    unsigned long   refcount;
  179    unsigned long   sum;
  180    unsigned char   *inverse_translations[4];
  181    int      readonly;
  182 };
  183 
  184 static struct uni_pagedir *dflt;
  185 
 
48 48   186 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
  187 {
  188    int j, glyph;
  189    unsigned short *t = translations[i];
  190    unsigned char *q;
  191    
48 - 192    if (!p) return;
 - 192   return
  193    q = p->inverse_translations[i];
  194 
48 - 195    if (!q) {
  196       q = p->inverse_translations[i] = (unsigned char *) 
  197          kmalloc(MAX_GLYPH, GFP_KERNEL);
48 - 198       if (!q) return;
 - 198     return
  199    }
  200    memset(q, 0, MAX_GLYPH);
  201 
12288 48   202    for (j = 0; j < E_TABSZ; j++) {
  203       glyph = conv_uni_to_pc(conp, t[j]);
9612 2676   204       if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
9612    204     T && T && T
 360   204     T && T && F
 - 204     T && F && _
 2316   204     F && _ && _
  205          /* prefer '-' above SHY etc. */
  206            q[glyph] = j;
  207       }
  208    }
  209 }
  210 
 
67   211 unsigned short *set_translate(int m, struct vc_data *vc)
  212 {
  213    inv_translate[vc->vc_num] = m;
67    214    return translations[m];
  215 }
  216 
  217 /*
  218  * Inverse translation is impossible for several reasons:
  219  * 1. The font<->character maps are not 1-1.
  220  * 2. The text may have been written while a different translation map
  221  *    was active, or using Unicode.
  222  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
  223  */
 
- 224 unsigned char inverse_translate(struct vc_data *conp, int glyph)
  225 {
  226    struct uni_pagedir *p;
- 227    if (glyph < 0 || glyph >= MAX_GLYPH)
 - 227   T || _
 - 227   F || T
 - 227   F || F
 - 228       return 0;
  229    else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
- 230        !p->inverse_translations[inv_translate[conp->vc_num]])
 - 230   !(T) || T
 - 230   !(F) || _
 - 230   !(T) || F
 - 231       return glyph;
    232    else
 - 233       return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
  234 }
  235 
 
- 236 static void update_user_maps(void)
  237 {
  238    int i;
  239    struct uni_pagedir *p, *q = NULL;
  240    
- 241    for (i = 0; i < MAX_NR_CONSOLES; i++) {
- 242       if (!vc_cons_allocated(i))
 - 243          continue;
  244       p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
- 245       if (p && p != q) {
 - 245     T && T
 - 245     T && F
 - 245     F && _
  246          set_inverse_transl(vc_cons[i].d, p, USER_MAP);
  247          q = p;
  248       }
  249    }
  250 }
  251 
  252 /*
  253  * Load customizable translation table
  254  * arg points to a 256 byte translation table.
  255  *
  256  * The "old" variants are for translation directly to font (using the
  257  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
  258  * Unicodes explicitly.
  259  */
 
- 260 int con_set_trans_old(unsigned char __user * arg)
  261 {
  262    int i;
  263    unsigned short *p = translations[USER_MAP];
  264 
- 265    if (!access_ok(VERIFY_READ, arg, E_TABSZ))
 - 266       return -EFAULT;
  267 
- 268    for (i=0; i<E_TABSZ ; i++) {
  269       unsigned char uc;
  270       __get_user(uc, arg+i);
  271       p[i] = UNI_DIRECT_BASE | uc;
  272    }
  273 
  274    update_user_maps();
 - 275    return 0;
  276 }
  277 
 
- 278 int con_get_trans_old(unsigned char __user * arg)
  279 {
  280    int i, ch;
  281    unsigned short *p = translations[USER_MAP];
  282 
- 283    if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
 - 284       return -EFAULT;
  285 
- 286    for (i=0; i<E_TABSZ ; i++)
  287      {
  288        ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
  289        __put_user((ch & ~0xff) ? 0 : ch, arg+i);
  290      }
 - 291    return 0;
  292 }
  293 
 
- 294 int con_set_trans_new(ushort __user * arg)
  295 {
  296    int i;
  297    unsigned short *p = translations[USER_MAP];
  298 
- 299    if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
 - 300       return -EFAULT;
  301 
- 302    for (i=0; i<E_TABSZ ; i++) {
  303       unsigned short us;
  304       __get_user(us, arg+i);
  305       p[i] = us;
  306    }
  307 
  308    update_user_maps();
 - 309    return 0;
  310 }
  311 
 
- 312 int con_get_trans_new(ushort __user * arg)
  313 {
  314    int i;
  315    unsigned short *p = translations[USER_MAP];
  316 
- 317    if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
 - 318       return -EFAULT;
  319 
- 320    for (i=0; i<E_TABSZ ; i++)
  321      __put_user(p[i], arg+i);
  322    
 - 323    return 0;
  324 }
  325 
  326 /*
  327  * Unicode -> current font conversion 
  328  *
  329  * A font has at most 512 chars, usually 256.
  330  * But one font position may represent several Unicode chars.
  331  * A hashtable is somewhat of a pain to deal with, so use a
  332  * "paged table" instead.  Simulation has shown the memory cost of
  333  * this 3-level paged table scheme to be comparable to a hash table.
  334  */
  335 
  336 extern u8 dfont_unicount[];   /* Defined in console_defmap.c */
  337 extern u16 dfont_unitable[];
  338 
 
60 60   339 static void con_release_unimap(struct uni_pagedir *p)
  340 {
  341    u16 **p1;
  342    int i, j;
  343 
60 - 344    if (p == dflt) dflt = NULL;  
1920 60   345    for (i = 0; i < 32; i++) {
120 1800   346       if ((p1 = p->uni_pgdir[i]) != NULL) {
3840 120   347          for (j = 0; j < 32; j++)
  348             kfree(p1[j]);
  349          kfree(p1);
  350       }
  351       p->uni_pgdir[i] = NULL;
  352    }
240 60   353    for (i = 0; i < 4; i++) {
  354       kfree(p->inverse_translations[i]);
  355       p->inverse_translations[i] = NULL;
  356    }
  357 }
  358 
 
73   359 void con_free_unimap(struct vc_data *vc)
  360 {
  361    struct uni_pagedir *p;
  362 
  363    p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
73 - 364    if (!p)
73    365       return;
  366    *vc->vc_uni_pagedir_loc = 0;
- 367    if (--p->refcount)
 - 368       return;
  369    con_release_unimap(p);
  370    kfree(p);
  371 }
  372   
 
72   373 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
  374 {
  375    int i, j, k;
  376    struct uni_pagedir *q;
  377    
816 12   378    for (i = 0; i < MAX_NR_CONSOLES; i++) {
684 132   379       if (!vc_cons_allocated(i))
684    380          continue;
  381       q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
72 60   382       if (!q || q == p || q->sum != p->sum)
 - 382     T || _ || _
12    382     F || T || _
60    382     F || F || T
 60   382     F || F || F
72    383          continue;
1920 60   384       for (j = 0; j < 32; j++) {
  385          u16 **p1, **q1;
  386          p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
1800 120   387          if (!p1 && !q1)
1800    387       T && T
 - 387       T && F
 120   387       F && _
1800    388             continue;
120 - 389          if (!p1 || !q1)
 - 389       T || _
 - 389       F || T
 120   389       F || F
 - 390             break;
3840 120   391          for (k = 0; k < 32; k++) {
2520 1320   392             if (!p1[k] && !q1[k])
2520    392         T && T
 - 392         T && F
 1320   392         F && _
2520    393                continue;
1320 - 394             if (!p1[k] || !q1[k])
 - 394         T || _
 - 394         F || T
 1320   394         F || F
 - 395                break;
1320 - 396             if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
 - 397                break;
  398          }
120 - 399          if (k < 32)
 - 400             break;
  401       }
60 - 402       if (j == 32) {
  403          q->refcount++;
  404          *conp->vc_uni_pagedir_loc = (unsigned long)q;
  405          con_release_unimap(p);
  406          kfree(p);
60    407          return 1;
  408       }
  409    }
12    410    return 0;
  411 }
  412 
  413 static int
 
19542   414 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
  415 {
  416    int i, n;
  417    u16 **p1, *p2;
  418 
150 19392   419    if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
  420       p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
150 - 421       if (!p1) return -ENOMEM;
 - 421     return - 12
4800 150   422       for (i = 0; i < 32; i++)
  423          p1[i] = NULL;
  424    }
  425 
1596 17946   426    if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
  427       p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
1596 - 428       if (!p2) return -ENOMEM;
 - 428     return - 12
  429       memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
  430    }
  431 
  432    p2[unicode & 0x3f] = fontpos;
  433    
  434    p->sum += (fontpos << 20) + unicode;
  435 
19542    436    return 0;
  437 }
  438 
  439 /* ui is a leftover from using a hashtable, but might be used again */
 
72   440 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
  441 {
  442    struct uni_pagedir *p, *q;
  443   
  444    p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
72 - 445    if (p && p->readonly) return -EIO;
 - 445   T && T
 66   445   T && F
   445   F && _
 - 445   return - 5
72 - 446    if (!p || --p->refcount) {
   446   T || _
66    446   F || T
 - 446   F || F
  447       q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
72 - 448       if (!q) {
- 449          if (p) p->refcount++;
 - 450          return -ENOMEM;
  451       }
  452       memset(q, 0, sizeof(*q));
  453       q->refcount=1;
  454       *vc->vc_uni_pagedir_loc = (unsigned long)q;
    455    } else {
- 456       if (p == dflt) dflt = NULL;
  457       p->refcount++;
  458       p->sum = 0;
  459       con_release_unimap(p);
  460    }
72    461    return 0;
  462 }
  463 
 
66   464 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
  465 {
  466    int err = 0, err1, i;
  467    struct uni_pagedir *p, *q;
  468 
  469    p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
66 - 470    if (p->readonly) return -EIO;