~ubuntu-branches/debian/sid/menu/sid

« back to all changes in this revision

Viewing changes to update-menus/adstring.cc

  • Committer: Bazaar Package Importer
  • Author(s): Bill Allombert
  • Date: 2005-05-24 10:34:47 UTC
  • mfrom: (1.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050524103447-9zu50so5d0nte3o9
Tags: 2.1.24
* The "head or tail" release 
* Fix .menus typo in menufile.5. Closes: #306564. Thanks Sean Finney.
* Add Vietnamese menu messages and menu sections translations.
  Thanks Clytie Siddall. Closes: #307450, #308953.
* Update Esperanto menu sections translation. Thanks MJ Ray.
* Add Esperanto menu messages translation. Thanks MJ Ray.
* Unfuzzy Norwegian Bokmål menu messages translation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <ctype.h>
2
 
#include "adstring.h"
3
 
#include "string.h"
4
 
#include <stdio.h>
5
 
#include <stdlib.h>
6
 
#include "regex.h"
7
 
#include <stdlib.h>
8
 
#include <strstream.h>
9
 
#include <iomanip.h>
10
 
#include <list.h>
11
 
#include <algo.h>
12
 
 
13
 
// ************* String.h replacement code:
14
 
int min(int i, int j){return i<j ? i : j;}
15
 
 
16
 
Regex::Regex(const char *s){
17
 
  patt=(struct re_pattern_buffer*)
18
 
    malloc(sizeof(struct re_pattern_buffer));
19
 
  patt->translate=0;
20
 
  patt->fastmap=0;
21
 
  patt->buffer=0;
22
 
  patt->allocated=0;
23
 
  re_compile_pattern(s,strlen(s),patt);
24
 
}
25
 
 
26
 
String upcase(const String &x){
27
 
  String s;
28
 
  for(string::size_type i=0;i< (string::size_type)x.length(); i++)
29
 
    s+=char(toupper(x[i]));
30
 
  return s;
31
 
}
32
 
 
33
 
#if 0
34
 
const char* String::chrstr() const{
35
 
  //This assumes vector doesn't free the memory for the last element.
36
 
  //I believe (but am not sure) that this is true.
37
 
 
38
 
  ((vector<char> &)buf).push_back('\0');
39
 
  ((vector<char> &)buf).pop_back();
40
 
  return &(buf[0]);
41
 
}
42
 
#endif
43
 
 
44
 
int readline(istream& s, String& x, 
45
 
             char terminator = '\n'){
46
 
  char buf[MAX_LINE*2];
47
 
  bool ret;
48
 
 
49
 
  ret=s.get(buf,sizeof(buf), terminator);
50
 
  x=String(buf);
51
 
  s.get(terminator);
52
 
  return ret;
53
 
}
54
 
 
55
 
// ************* "own" string handling code:
56
 
 
57
 
 
58
 
except_pi::except_pi(parsestream *p){
59
 
  pi=p;
60
 
}
61
 
 
62
 
except_pi_String::except_pi_String(parsestream *p, String s):except_pi(p){
63
 
  msg=s;
64
 
}
65
 
 
66
 
parseinfo::~parseinfo(void){
67
 
}
68
 
 
69
 
void except_pi::report(){
70
 
  string::size_type i;
71
 
  string::size_type startpos=0;
72
 
 
73
 
  if(pi){
74
 
    fprintf(stderr, 
75
 
            _("In file \"%s\", at (or in the definition that ends at) line %i:\n"),
76
 
            pi->filename().c_str(),
77
 
            pi->linenumber());
78
 
    
79
 
    if(pi->pos > 50)
80
 
      startpos=pi->pos - 50;
81
 
    
82
 
    if(startpos)
83
 
      cerr<<"[...]";
84
 
    cerr<<pi->buffer.substr(startpos)<<endl;
85
 
    
86
 
    if(startpos)
87
 
      cerr<<"[...]";
88
 
    for(i=1+startpos;i<pi->pos;i++)
89
 
      cerr<<" ";
90
 
    cerr<<"^"<<endl;
91
 
  } else {
92
 
    fprintf(stderr, 
93
 
            _("Somewhere in input file:\n"));
94
 
  }
95
 
  cerr<<message()<<endl;
96
 
}
97
 
void parsestream::preprocess(String &s){
98
 
  //disregards lines that start with a #
99
 
  //set filename if line starts with "!F"
100
 
  string::size_type i;
101
 
  String compat;
102
 
 
103
 
  i=0;
104
 
  while((i<s.length())&&isspace(s[i]))
105
 
    i++;
106
 
  if(i)
107
 
    s=s.after(i);
108
 
 
109
 
  if(!s.length())
110
 
    return;
111
 
 
112
 
  switch(s[0]){
113
 
  case '#':
114
 
    s=""; 
115
 
    return;
116
 
  case '!':
117
 
    if(s.length()>1){
118
 
        switch(s[1]){
119
 
        case 'F': 
120
 
          set_linenumber(0);
121
 
          set_filename(s.after(3));
122
 
          //cerr<<"filename="<<filename()<<", s.after="<<s.after(2)<<endl;
123
 
          s="";
124
 
          return;
125
 
        case 'L': 
126
 
          set_linenumber(Stringtoi(s.after(2))-1);
127
 
          //cerr<<"filename="<<filename()<<", s.after="<<s.after(2)<<endl;
128
 
          s="";
129
 
          return;
130
 
        case 'C':
131
 
          compat=s.after(3);
132
 
          if(compat == "menu-1")
133
 
            seteolmode(eol_newline);
134
 
          else if(compat == "menu-2")
135
 
            seteolmode(eol_semicolon);
136
 
          else 
137
 
            throw unknown_compat(this, compat);
138
 
          s="";
139
 
          return;
140
 
        default:
141
 
          if(s.contains("!include",0)){
142
 
            String t(s.after(strlen("!include ")));
143
 
            //cerr<<"HOI, t="<<t<<", filename()[0]="<<filename()[0]<<endl;
144
 
            if((t[0]=='/')|| 
145
 
               (fname.size()==0))
146
 
              new_file(t);
147
 
            else {
148
 
              String name=String_parent(filename()) + "/" + t;
149
 
              if(ifstream(name.c_str()))
150
 
                new_file(name);
151
 
              else{
152
 
                new_file(otherdir+'/'+t);
153
 
              }
154
 
            }
155
 
          }
156
 
          //(s==buffer now!) s="";
157
 
          return;
158
 
        }
159
 
    }
160
 
    return;
161
 
  default:;
162
 
  }
163
 
}
164
 
void parsestream::close_file(){
165
 
  //should delete i.back(), but only if !=stdin!
166
 
  
167
 
  int nu=i.size()-1;
168
 
  if(nu || !stdin_file)
169
 
    delete i[nu];
170
 
  i[nu]=NULL;
171
 
  if(i.size()>1){
172
 
    i.pop_back();
173
 
    lineno.pop_back();
174
 
    fname.pop_back();
175
 
  } else {
176
 
    throw endoffile(this);
177
 
  }
178
 
}
179
 
void parsestream::new_file(const String &s){
180
 
  ifstream *f=new ifstream(s.c_str());
181
 
  
182
 
  init(f,s,false);
183
 
  //??? 
184
 
}
185
 
void parsestream::new_line(){
186
 
  while(i.size()){
187
 
    if(!current_istr()||current_istr()->eof()){
188
 
      close_file();
189
 
      continue;
190
 
    }
191
 
    buffer="";
192
 
    pos=0;
193
 
    while(current_istr()->good()&&
194
 
          !(current_istr()->eof())&&
195
 
          !buffer.length()){
196
 
      readline(*current_istr(),buffer);
197
 
      set_linenumber(linenumber()+1);
198
 
      preprocess(buffer);
199
 
      buffer=rmtrailingspace(buffer);
200
 
    }
201
 
    while(current_istr()->good()&&
202
 
          !(current_istr()->eof())&&
203
 
          (((eolmode==eol_newline)&&(buffer[buffer.length()-1]=='\\'))||
204
 
           ((eolmode==eol_semicolon)&&(buffer[buffer.length()-1]!=';')))){
205
 
      String s;
206
 
      readline(*current_istr(),s);
207
 
      set_linenumber(linenumber()+1);
208
 
      switch(eolmode){
209
 
      case eol_newline:
210
 
        buffer=buffer.substr(0,buffer.length()-1)+" "+rmtrailingspace(s);
211
 
        break;
212
 
      case eol_semicolon:
213
 
        buffer=buffer+" "+rmtrailingspace(s);
214
 
        break;
215
 
      }
216
 
    }
217
 
    if(!buffer.length()){
218
 
      close_file();
219
 
      continue;
220
 
    }
221
 
    if(current_istr()->eof()&&
222
 
       buffer.length()&&
223
 
       (((eolmode==eol_newline)&&(buffer[buffer.length()-1]=='\\'))||
224
 
        ((eolmode==eol_semicolon)&&(buffer[buffer.length()-1]!=';')))){
225
 
      //a "\" at the end of a file: unconditional error (don't unwind etc)
226
 
      //(or no ; at eof, when eolmode=; . Same unconditional error.
227
 
      throw endoffile(this);
228
 
    }
229
 
    if(eolmode==eol_semicolon)
230
 
      if(buffer[buffer.length()-1]==';')
231
 
        buffer.erase(buffer.length()-1, 1);
232
 
    return;
233
 
  }
234
 
  if(in_constructor){
235
 
    return;
236
 
  } else
237
 
    throw endoffile(this);
238
 
}
239
 
 
240
 
char parsestream::get_char(){
241
 
  if(!buffer.length())
242
 
    throw endoffile(this);
243
 
  if(pos>=buffer.length())
244
 
    throw endofline(this);
245
 
  
246
 
  return buffer[pos++];
247
 
}
248
 
 
249
 
char parsestream::put_back(char c){
250
 
  if (c){
251
 
    if(pos){
252
 
      pos--;
253
 
      // buffer.at(pos,1)=String(c);
254
 
      buffer.replace(pos,1,c);
255
 
    } else
256
 
      buffer=c+buffer;
257
 
    
258
 
  }
259
 
  return c;
260
 
}
261
 
 
262
 
String parsestream::get_line(){
263
 
  String s;
264
 
  s=buffer.after(pos);
265
 
  if(s==String(""))
266
 
    throw endofline(this);
267
 
  buffer="";
268
 
  try{
269
 
    skip_line();
270
 
  }
271
 
  catch(endoffile){};
272
 
  return s;
273
 
}
274
 
 
275
 
String parsestream::get_name(){
276
 
  char c;
277
 
  String s;
278
 
  skip_space();
279
 
  try{
280
 
    while((c=get_char())&&
281
 
          (isalnum(c)||(c=='_')||(c=='-')||(c=='+')||(c=='.')))
282
 
      s+=c;
283
 
    if(c)
284
 
      put_back(c);
285
 
  } catch(endofline d){};
286
 
  return s;
287
 
}
288
 
 
289
 
String parsestream::get_name(const Regex &r){
290
 
  char str[2]={0,0};
291
 
  char &c=str[0];
292
 
  String s;
293
 
  skip_space();
294
 
  try{
295
 
    while((c=get_char())){
296
 
      if(re_match(r.pattern(), str, 1, 0, 0) > 0)
297
 
        s+=c;
298
 
      else
299
 
        break;
300
 
    }
301
 
    if(c)
302
 
      put_back(c);
303
 
  } catch(endofline){};
304
 
  return s;
305
 
}
306
 
String parsestream::get_eq_name(){
307
 
  char c;
308
 
  skip_space();
309
 
  c=get_char();
310
 
  if(c!='=')
311
 
    throw char_expected(this, "=");
312
 
  return get_name();
313
 
}
314
 
 
315
 
 
316
 
String parsestream::get_Stringconst(){
317
 
  char c;
318
 
  String s;
319
 
  skip_space();
320
 
  c=get_char();
321
 
  try{
322
 
    if(c=='\"'){
323
 
      while((c=get_char())&&(c!='\"')){
324
 
        if(c=='\\'){
325
 
          c=get_char();
326
 
          switch(c){
327
 
          case 't': c='\t'; break;
328
 
          case 'b': c='\b'; break;
329
 
          case 'n': c='\n'; break;
330
 
          default:; break;
331
 
          }
332
 
        }
333
 
        s+=c;
334
 
      }
335
 
      if(c!='\"')
336
 
        throw char_expected(this, "\"");
337
 
    } else{ //no " at begining
338
 
      s=String("") + c;
339
 
      while((c=get_char())&&!isspace(c))
340
 
        s+=c;
341
 
    }
342
 
  }catch(endofline p){};
343
 
  
344
 
  return s;
345
 
}
346
 
String parsestream::get_eq_Stringconst(){
347
 
  char c;
348
 
  skip_space();
349
 
  c=get_char();
350
 
  if(c!='=')
351
 
    throw char_expected(this, "=");
352
 
  return get_Stringconst();
353
 
}
354
 
 
355
 
bool parsestream::get_boolean(){
356
 
  String s;
357
 
  s=get_name();
358
 
 
359
 
  if(s==String("true"))
360
 
    return true;
361
 
  else if(s==String("false"))
362
 
    return false;
363
 
  else
364
 
    throw boolean_expected(this, s);
365
 
}
366
 
bool parsestream::get_eq_boolean(){
367
 
  char c;
368
 
  skip_space();
369
 
  c=get_char();
370
 
  if(c!='=')
371
 
    throw char_expected(this,"=");
372
 
  return get_boolean();
373
 
}
374
 
int parsestream::get_integer(){
375
 
  char c;
376
 
  String s;
377
 
 
378
 
  try{
379
 
    skip_space();
380
 
    while((c=get_char())&&((isdigit(c)||(c=='-'))))
381
 
      s+=c;
382
 
  } catch(endofline d){};
383
 
 
384
 
  return atoi(s.c_str());
385
 
}
386
 
 
387
 
int parsestream::get_eq_integer(){
388
 
  char c;
389
 
 
390
 
  skip_space();
391
 
  c=get_char();
392
 
  if(c!='=')
393
 
    throw char_expected(this, "=");
394
 
  return get_integer();
395
 
}
396
 
 
397
 
double parsestream::get_double(){
398
 
  char c;
399
 
  String s;
400
 
  
401
 
  skip_space();
402
 
  try{
403
 
    while((c=get_char())&&
404
 
         (isdigit(c)||
405
 
          (c=='.')||(c=='E')||(c=='e')||(c=='+')||(c=='-')))
406
 
      s+=c;
407
 
  } catch(endofline d){};
408
 
 
409
 
  return atof(s.c_str());       
410
 
}
411
 
double parsestream::get_eq_double(){
412
 
  char c;
413
 
  
414
 
  skip_space();
415
 
  c=get_char();
416
 
  if(c!='=')
417
 
    throw char_expected(this, "=");
418
 
 
419
 
  return get_double();
420
 
}
421
 
void parsestream::skip_line(){
422
 
  buffer="";
423
 
  try{
424
 
    new_line();
425
 
  }
426
 
  catch(endoffile d){};
427
 
}
428
 
void parsestream::skip_space(){
429
 
  char c;
430
 
  while(isspace(c=get_char()));  
431
 
  if(c)
432
 
    put_back(c);
433
 
}
434
 
void parsestream::skip_char(char expect){
435
 
  char buf[2]="a";
436
 
  char c=get_char();
437
 
  if(c!=expect){
438
 
    put_back(c);
439
 
    buf[0]=c;
440
 
    throw char_expected(this, buf);
441
 
  }
442
 
}
443
 
void parsestream::seteolmode(eol_type mode){
444
 
  eolmode=mode;
445
 
}
446
 
 
447
 
String rmtrailingspace(String &s){
448
 
  while(s.length()&&(isspace(s[s.length()-1])))
449
 
    s.erase(s.length()-1,1);
450
 
  return s;
451
 
}
452
 
 
453
 
 
454
 
 
455
 
String escape_doublequotes(const String &s){
456
 
  String t;
457
 
  string::size_type i;
458
 
  for(i=0;i!=s.length();i++){
459
 
    if(s[i]=='\"')
460
 
      t+='\\';
461
 
    t+=s[i];
462
 
  }
463
 
  return t;
464
 
}
465
 
 
466
 
String escapewith_String(const String &s, const String &esc,
467
 
                         const String &with){
468
 
  // call with: escape_String("hello $world, %dir", "$%", "\\")
469
 
  // returns:   "hello \$world, \%dir"
470
 
  String t;
471
 
  string::size_type i;
472
 
  for(i=0;i!=s.length();i++){
473
 
    if(esc.find(s[i])!=string::npos)
474
 
      t+=with;
475
 
    t+=s[i];
476
 
  }
477
 
  return t;
478
 
}
479
 
 
480
 
String escape_String(const String &s, const String &esc){
481
 
  // call with: escape_String("hello $world, %dir", "$%")
482
 
  // returns:   "hello \$world, \%dir"
483
 
  return escapewith_String(s,esc,"\\");
484
 
}
485
 
String cppesc_String(const String &s){
486
 
  String t;
487
 
  string::size_type i;
488
 
  for(i=0;i!=s.length();i++){
489
 
    if(!(isalnum(s[i])||(s[i]=='_')))
490
 
      t+='$'+itohexString(int(s[i]));
491
 
    else
492
 
      t+=s[i];
493
 
  }
494
 
  return t;
495
 
}
496
 
String tolower_String(const String &s){
497
 
  String t;
498
 
  for(string::size_type i=0; i<s.length(); i++)
499
 
    t+=char(tolower(s[i]));
500
 
  return t;
501
 
}
502
 
String toupper_String(const String &s){
503
 
  String t;
504
 
  for(string::size_type i=0; i<s.length(); i++)
505
 
    t+=char(toupper(s[i]));
506
 
  return t;
507
 
}
508
 
String replacewith_String(const String &s, const String &replace,
509
 
                          const String &with){
510
 
  // call with: replacewith_String("hello $world, %dir", "$% ", "123")
511
 
  // returns:   "hello31world,32dir"
512
 
  String t;
513
 
  string::size_type i,j;
514
 
  for(i=0;i!=s.length();i++){
515
 
    if((string::size_type)(j=replace.find(s[i]))!=string::npos)
516
 
      t+=with[j % with.length()];
517
 
    else
518
 
      t+=s[i];
519
 
  }
520
 
  return t;
521
 
}
522
 
 
523
 
String replace(String s,char match, char replace){
524
 
  string::size_type i;
525
 
  for(i=0;i!=s.length();i++)
526
 
    if(s[i]==match)
527
 
      s.replace(i,i+1,replace);
528
 
  return s;
529
 
}
530
 
String sort_hotkey(String str){
531
 
  String t;
532
 
  string::size_type i;
533
 
  string::size_type l=str.length();
534
 
  char *s=strdup(str.c_str());
535
 
 
536
 
  if(!l)
537
 
    return t;
538
 
 
539
 
  t=String("")+s[0];
540
 
  s[0]='\0';
541
 
  for(i=1;i!=l;i++)
542
 
    if((isspace(s[i-1])||ispunct(s[i-1]))&&isupper(s[i])){
543
 
      t+=s[i];
544
 
      s[i]='\0';
545
 
    }
546
 
  for(i=1;i!=l;i++)
547
 
    if((isspace(s[i-1])||ispunct(s[i-1]))&&isalnum(s[i])){
548
 
      t+=s[i];
549
 
      s[i]='\0';
550
 
    }
551
 
  for(i=1;i!=l;i++)
552
 
    if(isupper(s[i])){
553
 
      t+=s[i];
554
 
      s[i]='\0';
555
 
    }
556
 
  for(i=1;i!=l;i++)
557
 
    if(isalpha(s[i])){
558
 
      t+=s[i];
559
 
      s[i]='\0';
560
 
    }
561
 
  for(i=1;i!=l;i++)
562
 
    if(isalnum(s[i])){
563
 
      t+=s[i];
564
 
      s[i]='\0';
565
 
    }
566
 
  for(i=1;i!=l;i++)
567
 
    if(s[i]){
568
 
      t+=s[i];
569
 
      s[i]='\0';
570
 
    }
571
 
  free(s);
572
 
  return t;
573
 
}
574
 
 
575
 
int Stringtoi(const String &s){
576
 
  return atoi(s.c_str());
577
 
}
578
 
 
579
 
String itoString(int i){
580
 
  char s[MAX_LINE];
581
 
  ostrstream str(s,sizeof(s));
582
 
  str<<i<<ends;
583
 
  return s;
584
 
}
585
 
 
586
 
String itohexString(int i){
587
 
  char s[MAX_LINE];
588
 
  ostrstream str(s,sizeof(s));
589
 
  str<<setbase(16)<<i<<ends;
590
 
  return s;
591
 
}
592
 
 
593
 
 
594
 
String String_parent(String s){
595
 
  // String_parent("/Debian/Apps/Editors/Emacs") = "/Debian/Apps/Editors
596
 
  string::size_type  i,p;
597
 
  
598
 
  for(i=0,p=string::npos;(string::size_type)i!=s.length();i++)
599
 
    if(s[i]=='/')
600
 
      p=i;
601
 
  if(p==string::npos)
602
 
    return "";
603
 
  else
604
 
    return s.substr(0,p);
605
 
}
606
 
 
607
 
String String_basename(String s){
608
 
  String t;
609
 
  string::size_type i; 
610
 
  string::size_type p; //points to last encountered '/'
611
 
  string::size_type q; //points to last-but-one encountered '/'.
612
 
  
613
 
  for(i=0,p=string::npos,q=0;i!=s.length();i++)
614
 
    if(s[i]=='/'){
615
 
      q=p;
616
 
      p=i;
617
 
    }
618
 
  if(p==string::npos)
619
 
    return "";
620
 
  else
621
 
    return s.substr(q+1,p);
622
 
}
623
 
String String_stripdir(String s){
624
 
  String t;
625
 
  string::size_type i; 
626
 
  string::size_type p; //points to last encountered '/'
627
 
  
628
 
  for(i=0,p=string::npos;(string::size_type)i!=s.length();i++)
629
 
    if(s[i]=='/')
630
 
      p=i;
631
 
  if(p==string::npos)
632
 
    return s;
633
 
  else
634
 
    return s.substr(p+1,s.length());
635
 
}
636
 
 
637
 
String String_lastname(String s){
638
 
  //what `basename' in the shell returns...
639
 
  String t;
640
 
  string::size_type  i; 
641
 
  string::size_type  p; //points at last encountered '/'
642
 
 
643
 
  if(!s.size())
644
 
    return "";
645
 
 
646
 
  if(s[s.size()-1] == '/')
647
 
    s.erase(s.size()+1,1);
648
 
  
649
 
  for(i=0,p=string::npos;(string::size_type)i!=s.length();i++)
650
 
    if(s[i]=='/')
651
 
      p=i;
652
 
  if(p==string::npos)
653
 
    return "";
654
 
  else
655
 
    return s.substr(p+1);
656
 
}
657
 
 
658
 
void break_char(const String &sec,
659
 
                      StrVec &sec_vec,
660
 
                      char breakchar){
661
 
  String s;
662
 
  string::size_type i,j;
663
 
 
664
 
  if(!sec.size())
665
 
    return;
666
 
 
667
 
  if(sec[0]==breakchar) /* ignore first occurence of breachar */
668
 
    i=1;
669
 
  else
670
 
    i=0;
671
 
  while(true){
672
 
    while((i<sec.size())&&(isspace(sec[i])))
673
 
      i++;
674
 
    j=sec.find(breakchar,i);
675
 
    if(j!=string::npos)
676
 
      sec_vec.push_back(sec.substr(i,j-i));
677
 
    else{
678
 
      if(i!=sec.size())
679
 
        sec_vec.push_back(sec.substr(i));
680
 
      break;
681
 
    }
682
 
    i=j+1;
683
 
  }
684
 
}
685
 
 
686
 
 
687
 
void break_slashes(const String &sec,
688
 
                         StrVec &sec_vec){
689
 
  break_char(sec,sec_vec,'/');
690
 
}
691
 
void break_commas(const String &sec,
692
 
                         StrVec &sec_vec){
693
 
  break_char(sec,sec_vec,',');
694
 
}
695
 
 
696
 
 
697
 
String Sprintf(const char *s, String &str){
698
 
  char buf[MAX_LINE];
699
 
  snprintf(buf, sizeof(buf), s, str.c_str());
700
 
  return buf;
701
 
}
702
 
 
703
 
const char *ldgettext(const char *language,
704
 
                      const char *domain,
705
 
                      const char *msgid){
706
 
  /* this code comes from the gettext info page. It looks
707
 
     very inefficient (as though for every language change a new
708
 
     catalog file is opened), but tests show adding a language
709
 
     change like this doesn't get performance down very much
710
 
     (runtime goes `only' about 70% up, if switching between 2 
711
 
     languages, as compared to no swiching at all).
712
 
  */
713
 
  /* Change language.  */
714
 
  setenv ("LANGUAGE", language, 1);
715
 
  /* Make change known.  */
716
 
  {
717
 
    extern int  _nl_msg_cat_cntr;
718
 
    ++_nl_msg_cat_cntr;
719
 
  }
720
 
  return dgettext(domain, msgid);
721
 
}