1 // -*- mode:C++ ; compile-command: "g++ -I.. -g -c help.cc -Wall" -*- 2 //#define _SCL_SECURE_NO_WARNINGS 3 #include "giacPCH.h" 4 5 #include "path.h" 6 /* 7 * Copyright (C) 2000,14 B. Parisse, Institut Fourier, 38402 St Martin d'Heres 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 using namespace std; 23 #include <algorithm> 24 #include "gen.h" 25 #include "help.h" 26 #include <iostream> 27 #if !defined GIAC_HAS_STO_38 && !defined NSPIRE && !defined FXCG && !defined POCKETCAS 28 #include <fstream> 29 #endif 30 #include "global.h" 31 #ifdef HAVE_UNISTD_H 32 #include <unistd.h> 33 #endif 34 #ifdef KHICAS 35 #include "kdisplay.h" // for select_item 36 #endif 37 38 #if defined VISUALC || defined BESTA_OS 39 40 41 #define opendir FindFirstFile 42 #define readdir FindNextFile 43 #define closedir FindClose 44 #define DIR WIN32_FIND_DATA 45 #define GNUWINCE 1 46 47 #else // VISUALC or BESTA_OS 48 49 #ifdef HAVE_SYS_PARAM_H 50 #include <sys/param.h> 51 #endif 52 53 #if !defined BESTA_OS && !defined NSPIRE && !defined FXCG && !defined KHICAS // test should always return true 54 #include <dirent.h> 55 #endif 56 57 #endif // VISUALC or BESTA_OS 58 59 #include "input_lexer.h" 60 61 #ifndef NO_NAMESPACE_GIAC 62 namespace giac { 63 #endif // ndef NO_NAMESPACE_GIAC 64 65 const int HELP_LANGUAGES=5; 66 67 struct static_help_t { 68 const char * cmd_name; 69 const char * cmd_howto[HELP_LANGUAGES]; 70 const char * cmd_syntax; 71 const char * cmd_related; 72 const char * cmd_examples; 73 }; 74 75 const static_help_t static_help[]={ 76 #if defined NSPIRE_NEWLIB || defined NUMWORKS || (!defined RTOS_THREADX && !defined BESTA_OS && !defined GIAC_HAS_STO_38 && !defined(KHICAS) && !defined POCKETCAS) 77 #include "static_help.h" 78 #else 79 { "", { "", "", "", "",""}, "", "", "" }, 80 #endif 81 }; 82 83 const int static_help_size=sizeof(static_help)/sizeof(static_help_t); 84 85 struct static_help_sort { static_help_sortgiac::static_help_sort86 static_help_sort() {} operator ()giac::static_help_sort87 inline bool operator () (const static_help_t & a ,const static_help_t & b){ 88 return strcmp(a.cmd_name, b.cmd_name) < 0; 89 } 90 }; 91 mon_max(int a,int b)92 inline int mon_max(int a,int b){ 93 if (a>b) 94 return a; 95 else 96 return b; 97 } 98 seconddec(const pair<int,int> & a,const pair<int,int> & b)99 bool seconddec (const pair<int,int> & a,const pair<int,int> & b){ 100 return a.second>b.second; 101 } 102 103 // NB: cmd_name may be localized but related is not localized has_static_help(const char * & cmd_name,int lang,const char * & howto,const char * & syntax,const char * & related,const char * & examples)104 bool has_static_help(const char * & cmd_name,int lang,const char * & howto,const char * & syntax,const char * & related,const char * & examples){ 105 #ifdef GIAC_HAS_STO_38 106 const char nullstring[]=" "; 107 #else 108 const char nullstring[]=""; 109 #endif 110 if (lang<=0) 111 lang=2; 112 if (lang>HELP_LANGUAGES) 113 lang=2; 114 string s=unlocalize(cmd_name); 115 int l=int(s.size()); 116 if (l==0) return false; 117 if ( (l>2) && (s[0]=='\'') && (s[l-1]=='\'') ) 118 s=s.substr(1,l-2); 119 #ifdef KHICAS 120 int pos=0,kk,ks=s.size(); 121 for (;pos<static_help_size;++pos){ 122 if (strcmp(static_help[pos].cmd_name,s.c_str())>=0) 123 break; 124 } 125 const char * items[1+static_help_size]; 126 kk=0; 127 for (;pos<static_help_size;++kk,++pos){ 128 const static_help_t & sh=static_help[pos]; 129 const char * ptr=sh.cmd_name; 130 if (strcmp(ptr,s.c_str())==0){ 131 howto=sh.cmd_howto[lang-1]; 132 if (!howto) 133 howto=sh.cmd_howto[1]; 134 syntax=sh.cmd_syntax; 135 if (!syntax) 136 syntax=nullstring; 137 related=sh.cmd_related; 138 if (!related) 139 related=nullstring; 140 examples=sh.cmd_examples; 141 if (!examples) 142 examples=nullstring; 143 return true; 144 } 145 if (strlen(ptr)<ks || strncmp(ptr,s.c_str(),ks)!=0) 146 break; 147 items[kk]=ptr; 148 } 149 items[kk]=0; 150 int r=select_item(items,"Select completion",false); 151 if (r<0) 152 return false; 153 cmd_name=items[r]; 154 return has_static_help(items[r],lang,howto,syntax,related,examples); 155 #endif 156 static_help_t h={s.c_str(),{0,0,0,0,0},0,0,0}; 157 std::pair<const static_help_t *,const static_help_t *> p=equal_range(static_help,static_help+static_help_size,h,static_help_sort()); 158 if (p.first!=p.second && p.first!=static_help+static_help_size){ 159 howto=p.first->cmd_howto[lang-1]; 160 if (!howto) 161 howto=p.first->cmd_howto[1]; 162 syntax=p.first->cmd_syntax; 163 if (!syntax) 164 syntax=nullstring; 165 related=p.first->cmd_related; 166 if (!related) 167 related=nullstring; 168 examples=p.first->cmd_examples; 169 if (!examples) 170 examples=nullstring; 171 return true; 172 } 173 #if defined EMCC 174 // Find closest string 175 syntax=nullstring; 176 related=nullstring; 177 static string res; 178 res=""; 179 int best_score=0,cur_score; 180 vector< pair<int,int> > best_j; 181 for (int j=0;j<static_help_size;++j){ 182 cur_score=score(s,static_help[j].cmd_name); 183 if (cur_score>best_score){ 184 best_score=cur_score; 185 vector< pair<int,int> > tmp; 186 for (unsigned k=0;k<best_j.size();++k){ 187 if (best_j[k].second>=best_score-6) 188 tmp.push_back(best_j[k]); 189 } 190 best_j=tmp; 191 best_j.push_back(pair<int,int>(j,cur_score)); 192 continue; 193 } 194 if (cur_score>=mon_max(best_score-6,0)){ 195 best_j.push_back(pair<int,int>(j,cur_score)); 196 } 197 } 198 if (best_score>0){ 199 sort(best_j.begin(),best_j.end(),seconddec); 200 vector< pair<int,int> >::iterator it=best_j.begin(),itend=best_j.end(); 201 for (int k=1;(k<10) && (it!=itend);++k,++it){ 202 res = res+static_help[it->first].cmd_name; 203 res = res+","; 204 } 205 if (!res.empty()) 206 res=res.substr(0,res.size()-1); 207 } 208 static string syn; 209 syn = gettext("Best match has score ") + printint(best_score) + "\n"; 210 howto = syn.c_str(); 211 examples = res.c_str(); 212 return true; 213 #else 214 return false; 215 #endif 216 } 217 output_quote(const string s)218 static std::string output_quote(const string s){ 219 string res; 220 int ss=int(s.size()); 221 for (int i=0;i<ss;++i){ 222 switch (s[i]){ 223 case '"': 224 case '\\': 225 res += '\\'; 226 default: 227 res += s[i]; 228 } 229 } 230 return res; 231 } 232 233 // Run ./icas with export GIAC_DEBUG=-2 to print static_help.h and static_help_w.h, then sort in emacs 234 // /usr/share/giac/doc/fr or en -> longhelp.js or longhelp_en.js: html_mtt 235 // replace string \244 with : 236 // macro replace /usr/share/giac/doc/en/cascmd_en/ with ' and #... with ' 237 // longhelp*.js should begin with var longhelp = { 238 // and end with }; output_static_help(vector<aide> & v,const vector<int> & langv)239 static bool output_static_help(vector<aide> & v,const vector<int> & langv){ 240 #if !defined NSPIRE && !defined FXCG && !defined GIAC_HAS_STO_38 241 add_language(5,context0); // add german help de/aide_cas 242 cout << "Generating xcascmds, for UI.xcascmds in xcas.js, sort and esc-x replace-string ctrl-Q ctrl-j ret ret" << endl; 243 cout << "Copy in python.js. For xcasmod.js, replace \",\" by | " << endl; 244 cout << "Generating static_help.h (sort it in emacs)" << endl; 245 cout << "Generating static_help_w.h (same but UTF16)" << endl; 246 ofstream cmds("xcascmds"); 247 cmds << "[" << endl; 248 ofstream of("static_help.h"); 249 vector<aide>::iterator it=v.begin(),itend=v.end(); 250 for (;it!=itend;){ 251 cmds << '"' << output_quote(it->cmd_name) << '"' << "," << endl; 252 of << "{"; 253 of << '"' << output_quote(it->cmd_name) << '"' << ","; 254 std::vector<localized_string> & blabla = it->blabla; 255 sort(blabla.begin(),blabla.end()); 256 int blablapos=0; 257 of << "{"; 258 for (int i=0;i<HELP_LANGUAGES;i++){ 259 if (i+1==blabla[blablapos].language && equalposcomp(langv,i+1)){ 260 of << '"' << output_quote(blabla[blablapos].chaine) << '"' ; 261 blablapos++; 262 } 263 else 264 of << 0 ; 265 if (i==HELP_LANGUAGES-1) 266 of << '}'; 267 else 268 of << ','; 269 } 270 of << "," << '"' << output_quote(it->syntax) << '"' << ',' ; 271 std::vector<std::string> & examples = it->examples; 272 int bs=int(examples.size()); 273 if (bs){ 274 of << '"'; 275 for (int i=0;i<bs;i++){ 276 of << output_quote(examples[i]) ; 277 if (i==bs-1) 278 of << '"'; 279 else 280 of << ';'; 281 } 282 } 283 else 284 of << 0 ; 285 of << "," ; 286 std::vector<indexed_string> & related = it->related; 287 bs=int(related.size()); 288 if (bs){ 289 of << '"'; 290 for (int i=0;i<bs;i++){ 291 of << output_quote(related[i].chaine) ; 292 if (i==bs-1) 293 of << '"'; 294 else 295 of << ','; 296 } 297 } 298 else 299 of << 0; 300 of << "}"; 301 ++it; 302 if (it==itend) 303 break; 304 of << "," << endl; 305 } 306 cmds << "]" << endl; 307 of << endl; 308 ofstream ofw("static_help_w.h"); 309 ofstream ofwindex("index_w.h"); 310 ofwindex << "const TChooseItem index_w[]={" << endl; 311 for (it=v.begin();it!=itend;){ 312 ofw << "{"; 313 string cmd=it->cmd_name; 314 ofw << 'L' << '"' << output_quote(cmd) << '"' << ","; 315 if (cmd.size()>16) 316 cmd=cmd.substr(0,16); 317 ofwindex << "{NULL,NULL, " << 'L' << '"' << output_quote(cmd) << '"' << ", HIDVoid }" ; 318 std::vector<localized_string> & blabla = it->blabla; 319 sort(blabla.begin(),blabla.end()); 320 int bs=int(blabla.size()); 321 ofw << "{"; 322 for (int i=0;i<HELP_LANGUAGES;i++){ 323 if (i<bs && equalposcomp(langv,i+1)) 324 ofw << 'L' << '"' << output_quote(blabla[i].chaine) << '"' ; 325 else 326 ofw << 0 ; 327 if (i==HELP_LANGUAGES-1) 328 ofw << '}'; 329 else 330 ofw << ','; 331 } 332 ofw << ",L" << '"' << output_quote(it->cmd_name) << '(' << output_quote(it->syntax) << ')' << '"' << ',' ; 333 std::vector<std::string> & examples = it->examples; 334 bs=int(examples.size()); 335 if (bs>=1){ 336 ofw << 'L' << '"'; 337 ofw << output_quote(examples[0]) ; 338 ofw << '"' << ','; 339 if (bs>=2){ 340 ofw << 'L' << '"'; 341 ofw << output_quote(examples[1]) ; 342 ofw << '"' << ','; 343 } 344 else 345 ofw << 0 << ","; 346 } 347 else 348 ofw << 0 << "," << 0 << ","; 349 std::vector<indexed_string> & related = it->related; 350 bs=int(related.size()); 351 if (bs>=1){ 352 ofw << 'L' << '"'; 353 ofw << output_quote(related[0].chaine) ; 354 ofw << '"' << ','; 355 if (bs>=2){ 356 ofw << 'L' << '"'; 357 ofw << output_quote(related[1].chaine) ; 358 ofw << '"' << ','; 359 } 360 else 361 ofw << 0 << ","; 362 } 363 else 364 ofw << 0 << "," << 0 << ","; 365 ofw << "}"; 366 ++it; 367 if (it==itend) 368 break; 369 ofw << "," << endl; 370 ofwindex << "," << endl; 371 } 372 ofw << endl; 373 ofwindex << "};" << endl; 374 #endif 375 return true; 376 } 377 operator <(const indexed_string & is1,const indexed_string & is2)378 bool operator < (const indexed_string & is1,const indexed_string & is2){ 379 if (is1.index!=is2.index) return is1.index<is2.index; 380 return (is1.chaine<is2.chaine); 381 } 382 383 const char default_helpfile[]=giac_aide_location; // help filename 384 const int HELP_MAXLENSIZE = 1600; // less than 20 lines of 80 chars 385 printint(int i)386 string printint(int i){ 387 if (!i) 388 return string("0"); 389 if (i<0) 390 return string("-")+printint(-i); 391 int length = (int) std::floor(std::log10((double) i)); 392 #if defined VISUALC || defined BESTA_OS 393 char * s =new char[length+2]; 394 #else 395 char s[length+2]; 396 #endif 397 s[length+1]=0; 398 for (;length>-1;--length,i/=10) 399 s[length]=i%10+'0'; 400 #if defined VISUALC || defined BESTA_OS 401 string res=s; 402 delete [] s; 403 return res; 404 #else 405 return s; 406 #endif 407 } 408 max(int a,int b,int c)409 inline int max(int a,int b,int c){ 410 if (a>=b){ 411 if (a>=c) 412 return a; 413 else 414 return c; 415 } 416 if (b>=c) 417 return b; 418 else 419 return c; 420 } 421 score(const string & s,const string & t)422 int score(const string & s,const string & t){ 423 int ls=int(s.size()),lt=int(t.size()); 424 if (!ls) return -1; 425 vector<int> cur_l, new_l(lt+1,0); 426 for (int j=0;j<=lt;++j) 427 cur_l.push_back(-j); 428 vector<int>::iterator newbeg=new_l.begin(),newend=new_l.end(),newit=newbeg; 429 vector<int>::iterator curbeg=cur_l.begin(),curit;//curend=cur_l.end(), 430 for (int i=0;i<ls;++i){ 431 newit=newbeg; 432 curit=curbeg; 433 int oldres=-i,res; 434 for (int j=0;j<lt;++curit,++j){ 435 *newit=oldres; 436 if (s[i]==t[j]) 437 res=max(oldres-1,*(curit+1)-1,*curit+3); 438 else { 439 if (abs(s[i]-t[j])==32) 440 res=max(oldres-1,*(curit+1)-1,*curit+2); 441 else 442 res=max(oldres-1,*(curit+1)-1,*curit-2); 443 } 444 ++newit; 445 oldres=res; 446 } 447 *newit=oldres; 448 copy(newbeg,newend,curbeg); 449 } 450 // alignement would be return *newit; 451 // we modify the returned value to increase the weight of the first char 452 if (!s.empty() && !t.empty()){ 453 if (s[0]==t[0]) 454 return * newit+2; 455 else 456 return *newit-2; 457 } 458 return *newit; 459 } 460 alpha_order(const aide & a1,const aide & a2)461 bool alpha_order(const aide & a1,const aide & a2){ 462 string s1 =a1.cmd_name; 463 string s2 =a2.cmd_name; 464 for (unsigned i=0;i<s1.size();++i) 465 s1[i]=tolower(s1[i]); 466 for (unsigned i=0;i<s2.size();++i) 467 s2[i]=tolower(s2[i]); 468 if (s1!=s2) 469 return s1<s2; 470 return a1.cmd_name< a2.cmd_name; 471 } 472 find_synonymes(const std::string & cmd_name,vector<localized_string> & current_synonymes)473 static void find_synonymes(const std::string & cmd_name,vector<localized_string> & current_synonymes){ 474 current_synonymes.clear(); 475 // parse curren_aide.cmd_name for synonyms 476 string s=cmd_name,s1; 477 int i; 478 for (;;){ 479 // cout << s << endl; 480 i=int(s.find(' ')); 481 if (i<=0){ 482 if (!s.empty()) 483 current_synonymes.push_back(localized_string(0,s)); 484 break; 485 } 486 s1=s.substr(0,i); 487 current_synonymes.push_back(localized_string(0,s1)); 488 /* add also keyword translations of s1 489 multimap<string,localized_string>::iterator it=back_lexer_localization_map().find(s1),backend=back_lexer_localization_map().end(),itend=back_lexer_localization_map().upper_bound(s1); 490 if (it!=backend){ 491 for (;it!=itend;++it){ 492 current_synonymes.push_back(it->second); 493 } 494 } 495 */ 496 s=s.substr(i+1,s.size()-i-1); 497 } // end for (;;) 498 } 499 500 readhelp(const char * f_name,int & count,bool warn)501 vector<aide> readhelp(const char * f_name,int & count,bool warn){ 502 vector<aide> v(1); 503 readhelp(v,f_name,count,warn); 504 return v; 505 } 506 // FIXME: aide_cas may end with synonyms (# cmd synonym1 ...) readhelp(vector<aide> & v,const char * f_name,int & count,bool warn)507 void readhelp(vector<aide> & v,const char * f_name,int & count,bool warn){ 508 count=0; 509 #if !defined NSPIRE && !defined FXCG && !defined GIAC_HAS_STO_38 510 if (access(f_name,R_OK)){ 511 if (warn) 512 std::cerr << "Help file " << f_name << " not found" << endl; 513 return ; 514 } 515 // v.reserve(1600); 516 ifstream f(f_name); 517 char fs[HELP_MAXLENSIZE+1]; 518 vector<localized_string> current_blabla; 519 vector<indexed_string> current_related; 520 vector<string> current_examples; 521 aide current_aide; 522 vector<int> vposition; 523 int vpositions; 524 string current_line; 525 vector<localized_string> current_synonymes; 526 while (f){ 527 f.getline(fs,HELP_MAXLENSIZE,'\n'); 528 if (!fs[0]) 529 continue; 530 current_line=fs; 531 if (fs[0]=='#'){ 532 current_aide.blabla=current_blabla; 533 current_aide.examples=current_examples; 534 current_aide.related=current_related; 535 if (!current_aide.cmd_name.empty()){ 536 find_synonymes(current_aide.cmd_name,current_synonymes); 537 current_aide.synonymes=current_synonymes; 538 vector<localized_string>::const_iterator it=current_synonymes.begin(),itend=current_synonymes.end(); 539 vpositions=int(vposition.size()); 540 for (int pos=0;it!=itend;++it,++pos){ 541 current_aide.cmd_name=it->chaine; 542 if (pos<vpositions) 543 v[vposition[pos]]=current_aide; 544 else 545 v.push_back(current_aide); 546 ++count; 547 } 548 } // end if (!current_aide.cmd_name.empty()) 549 current_blabla.clear(); 550 current_examples.clear(); 551 current_related.clear(); 552 vposition.clear(); 553 current_aide.cmd_name=current_line.size()>2?current_line.substr(2,current_line.size()-2):""; 554 // search if cmd_name is already present in v 555 // if so set vposition, current_blabla/examples/related accordingly 556 find_synonymes(current_aide.cmd_name,current_synonymes); 557 vector<localized_string>::const_iterator itbeg=current_synonymes.begin(),itend=current_synonymes.end(),it; 558 vector<aide>::iterator itpos; 559 for (it=itbeg;it!=itend;++it){ 560 itpos=lower_bound(v.begin(),v.end(),current_aide,alpha_order); 561 if (itpos!=v.end()){ 562 // --itpos; 563 if (itpos->cmd_name==it->chaine){ // already documented 564 current_synonymes=itpos->synonymes; 565 current_blabla=itpos->blabla; 566 current_examples=itpos->examples; 567 current_related=itpos->related; 568 vposition.push_back(int(itpos-v.begin())); 569 } 570 } 571 } 572 continue; 573 } 574 // look for space 575 int l=int(current_line.find_first_of(' ')); 576 if ( (l==1) && (current_line[0]=='0') ){ 577 int cs=int(current_line.size()); 578 while (l<cs && current_line[l]==' '){ ++l; } 579 current_aide.syntax=current_line.substr(l,cs-l); 580 continue; 581 } 582 int n=0; 583 bool positif=true; 584 int i=0; 585 if (current_line[i]=='-'){ 586 positif=false; 587 ++i; 588 } 589 for (;i<l;++i){ 590 if ((current_line[i]<'0') || (current_line[i]>'9')){ 591 n=0; 592 break; 593 } 594 else 595 n=10*n+(current_line[i]-int('0')); 596 } 597 if (!positif) 598 n=-n; 599 if (n>0) 600 current_blabla.push_back(localized_string(n,current_line.substr(l+1,current_line.size()-l))); 601 else { 602 if (n<0) 603 current_related.push_back(indexed_string(-n,current_line.substr(l+1,current_line.size()-l))); 604 else 605 current_examples.push_back(current_line); 606 } 607 } // end reading help from file 608 if (!current_aide.cmd_name.empty()){ 609 current_aide.synonymes=vector<localized_string>(1,localized_string(0,current_aide.cmd_name)); 610 current_aide.blabla=current_blabla; 611 current_aide.examples=current_examples; 612 current_aide.related=current_related; 613 v.push_back(current_aide); 614 count++; 615 } 616 sort(v.begin(),v.end(),alpha_order); 617 if (debug_infolevel==-2){ 618 vector<int> langv; 619 langv.push_back(1); 620 langv.push_back(2); 621 langv.push_back(3); 622 langv.push_back(4); 623 langv.push_back(5); 624 output_static_help(v,langv); 625 } 626 #endif 627 } 628 add_synonyme_name_to_examples(const aide & a)629 static aide add_synonyme_name_to_examples(const aide & a){ 630 aide res(a); 631 std::vector<std::string>::iterator it=res.examples.begin(),itend=res.examples.end(); 632 for (;it!=itend;++it){ 633 if (!it->empty() && (*it)[0]==' ') 634 continue; 635 // look for a ( 636 unsigned i=unsigned(it->find('(')); 637 if (i>0 && i<it->size()){ // check whether the beginning of the string is in synonyms 638 string cmd=it->substr(0,i); 639 std::vector<localized_string>::const_iterator jt=res.synonymes.begin(),jtend=res.synonymes.end(); 640 for (;jt!=jtend;++jt){ 641 if (jt->chaine==cmd) 642 break; 643 } 644 if (jt!=jtend) // Yes, replace it 645 *it=res.cmd_name+it->substr(i,it->size()-i); 646 else 647 *it=res.cmd_name+'('+*it+')'; 648 } 649 else 650 *it=res.cmd_name+'('+*it+')'; 651 } 652 return res; 653 } 654 helpon(const string & demande,const vector<aide> & v,int language,int count,bool with_op)655 aide helpon(const string & demande,const vector<aide> & v,int language,int count,bool with_op){ 656 aide result; 657 string current(demande); 658 if (with_op) 659 result.syntax = gettext("No help available for ") +current +"\n"; 660 else 661 result.syntax="NULL"; 662 if (!count){ 663 return result; 664 } 665 for (int i=1;;++i){ 666 if (i==count){ 667 if (!with_op) 668 return result; 669 // Find closest string 670 int best_score=0,cur_score; 671 vector< pair<int,int> > best_j; 672 for (int j=1;j<count;++j){ 673 cur_score=score(current,v[j].cmd_name); 674 if (cur_score>best_score){ 675 best_score=cur_score; 676 vector< pair<int,int> > tmp; 677 for (unsigned k=0;k<best_j.size();++k){ 678 if (best_j[k].second>=best_score-6) 679 tmp.push_back(best_j[k]); 680 } 681 best_j=tmp; 682 best_j.push_back(pair<int,int>(j,cur_score)); 683 continue; 684 } 685 if (cur_score>=mon_max(best_score-6,0)){ 686 best_j.push_back(pair<int,int>(j,cur_score)); 687 } 688 } 689 if (best_score>0){ 690 sort(best_j.begin(),best_j.end(),seconddec); 691 vector< pair<int,int> >::iterator it=best_j.begin(),itend=best_j.end(); 692 for (int k=1;(k<10) && (it!=itend);++k,++it) 693 result.related.push_back(indexed_string(k,v[it->first].cmd_name)); 694 } 695 result.syntax += gettext("Best match has score ") + printint(best_score) + "\n"; 696 result.cmd_name = current; 697 return result; 698 } 699 if (current==v[i].cmd_name){ 700 result=v[i]; 701 if (!with_op) 702 return add_synonyme_name_to_examples(result); 703 result.syntax= current + "(" +result.syntax +")\n"; 704 return add_synonyme_name_to_examples(result); 705 } 706 } // end for i 707 } 708 writehelp(const aide & cur_aide,int language)709 string writehelp(const aide & cur_aide,int language){ 710 string result=cur_aide.syntax; 711 vector<localized_string>::const_iterator it=cur_aide.blabla.begin(),itend=cur_aide.blabla.end(); 712 for (;it!=itend;++it){ 713 if (it->language==language){ 714 result += it->chaine +'\n' ; 715 break; 716 } 717 } 718 vector<indexed_string>::const_iterator iti=cur_aide.related.begin(),itiend=cur_aide.related.end(); 719 if (itiend!=iti){ 720 result += gettext("See also: "); 721 for (;iti!=itiend;++iti){ 722 result += printint(iti->index) + "/ " + iti->chaine + " "; 723 } 724 result += '\n' ; 725 } 726 vector<string>::const_iterator its=cur_aide.examples.begin(),itsend=cur_aide.examples.end(); 727 for (int i=1;its!=itsend;++its,++i){ 728 string current = "Ex" + printint(i)+':'+*its ; 729 result += current +'\n' ; 730 // system(current.c_str()); 731 } 732 return result; 733 } 734 735 #if !defined(NSPIRE_NEWLIB) && !defined(RTOS_THREADX) && !defined(EMCC) &&!defined(NSPIRE) && !defined FXCG && !defined(KHICAS) && !defined GIAC_HAS_STO_38 736 multimap<string,string> html_mtt,html_mall; 737 std::vector<std::string> html_vtt,html_vall; 738 739 // WARNING rebuilding caches works with old version of hevea (1.10) but not with hevea 2.29 740 // find index nodes in file file find_index(const std::string & current_dir,const std::string & file,multimap<std::string,std::string> & mtt,multimap<std::string,std::string> & mall,bool is_index=false,bool warn=false)741 static bool find_index(const std::string & current_dir,const std::string & file,multimap<std::string,std::string>&mtt,multimap<std::string,std::string>&mall,bool is_index=false,bool warn=false){ 742 if (access(file.c_str(),R_OK)) 743 return false; 744 ifstream i(file.c_str()); 745 // Skip navigation panel 746 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 747 char * buf=new char[BUFFER_SIZE+1]; 748 #else 749 char buf[BUFFER_SIZE+1]; 750 #endif 751 for (;i && !i.eof();){ 752 i.getline(buf,BUFFER_SIZE,'\n'); 753 string s(buf),stmp; 754 if (s=="<!--End of Navigation Panel-->") // latex2html? 755 break; 756 int t=int(s.size()); 757 if (t>24 && ((stmp=s.substr(t-24,24))=="<LI CLASS=\"li-indexenv\">" || stmp=="<li class=\"li-indexenv\">")){ 758 // hevea file contains index 759 for (;i && !i.eof(); ){ 760 i.getline(buf,BUFFER_SIZE,'\n'); 761 s=buf; 762 t=int(s.size()); 763 if (t>29 && ((stmp=s.substr(0,29))=="</LI><LI CLASS=\"li-indexenv\">" || stmp=="</li><li class=\"li-indexenv\">")){ 764 s=s.substr(29,s.size()-29); 765 t=int(s.size()); 766 if (!t || s[0]=='<') // skip index words with special color/font 767 continue; 768 int endcmd=int(s.find("<")); // position of end of commandname 769 if (endcmd>2 && endcmd<t){ 770 string cmdname=s.substr(0,endcmd-2); 771 s=s.substr(endcmd,t-endcmd); // s has all the links 772 vector<string> hrefs; 773 for (;;){ 774 t=int(s.size()); 775 endcmd=int(s.find("<a href=\"")); 776 if (endcmd<0 || endcmd+9>=t){ 777 endcmd=int(s.find("<A HREF=\"")); 778 if (endcmd<0 || endcmd+9>=t) 779 break; 780 } 781 s=s.substr(endcmd+9,s.size()-endcmd-9); 782 t=int(s.size()); 783 endcmd=int(s.find("\"")); 784 if (endcmd<0 || endcmd+2>=t) 785 break; 786 string link=s.substr(0,endcmd); 787 if (link[0]=='#') 788 link = file + link; 789 else 790 link = current_dir + link; 791 s=s.substr(endcmd+2,s.size()-endcmd-2); 792 t=int(s.size()); 793 if (t<3) 794 break; 795 if (s.substr(0,3)=="<B>" || (t>30 && s.substr(0,29)=="<span style=\"font-weight:bold")) 796 hrefs.insert(hrefs.begin(),link); 797 else 798 hrefs.push_back(link); 799 } 800 vector<string>::const_iterator it=hrefs.begin(),itend=hrefs.end(); 801 for (;it!=itend;++it){ 802 if (it==hrefs.begin()) 803 mtt.insert(pair<string,string>(cmdname,*it)); 804 mall.insert(pair<string,string>(cmdname,*it)); 805 } 806 } // if (endcmd>2 && endcmd<t) 807 } // if (t>29 &&... 808 } // for (;i && !i.eof();) end of file 809 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 810 delete [] buf; 811 #endif 812 return true; 813 } // end hevea file with index 814 // latex2html only? 815 if (t>14 && s.substr(t-14,14)=="Index</A></B> "){ 816 // look in the corresponding index file instead 817 int t1=int(s.find("HREF"))+6; 818 if (t1>=0 && t1<t-16){ 819 s=s.substr(t1,t-16-t1); 820 if (warn) 821 cerr << "Using index " << s << endl; 822 find_index(current_dir,current_dir+s,mtt,mall,true,warn); 823 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 824 delete [] buf; 825 #endif 826 return true; 827 } 828 } 829 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 830 delete [] buf; 831 #endif 832 } 833 string tmp; 834 char c; 835 for (;i && !i.eof();){ 836 // read i search for a <A word 837 i >> tmp; 838 int l=int(tmp.size()); 839 string tts; 840 if (is_index){ 841 if (l<13) 842 continue; 843 int tmpl=0; 844 if (tmp.substr(0,8)=="<STRONG>") 845 tmpl=8; 846 if (tmp.substr(0,12)=="<DT><STRONG>") 847 tmpl=12; 848 if (!tmpl) 849 continue; 850 int l1=int(tmp.find("</STRONG>")); 851 if (l1<=tmpl || l1>=l) 852 continue; 853 tts=tmp.substr(tmpl,l1-tmpl); 854 } 855 else { 856 if (l<2 || tmp.substr(l-2,2)!="<A") 857 continue; 858 } 859 // read the link 860 tmp=""; 861 int s=0; 862 for (;i && !i.eof();){ 863 i.get(c); 864 ++s; 865 tmp += c; 866 if (s>4 && tmp.substr(s-4,4)=="<DT>"){ 867 // no <B> found, truncate tmp to the first </A> found 868 int l=int(tmp.find("</A>")); 869 if (l<s && l>0) 870 tmp=tmp.substr(0,l); 871 s=int(tmp.size()); 872 break; 873 } 874 if (s>8 && tmp.substr(s-8,8)=="</B></A>"){ 875 // Find backward the first occurence of <A 876 int l=s-8; 877 for (;l>0;--l){ 878 if (tmp[l]=='<' && tmp[l+1]=='A') 879 break; 880 } 881 if (l){ 882 tmp=tmp.substr(l,s-l); 883 s -= l; 884 } 885 break; 886 } 887 } 888 // cerr << tmp << endl; 889 // analysis, search for HREF 890 int href=int(tmp.find("HREF=\"")); 891 if (href<0 || href+6>=s) 892 continue; 893 string hrefs(current_dir); 894 int hrefend=0; 895 for (int j=href+6;j<s;++j){ 896 if (tmp[j]=='"'){ // remove HREF= 897 hrefend=j+1; 898 break; 899 } 900 hrefs += tmp[j]; 901 } 902 if (!hrefend) 903 continue; 904 if (is_index){ 905 mtt.insert(pair<string,string>(tts,hrefs)); 906 mall.insert(pair<string,string>(tts,hrefs)); 907 } 908 else { 909 // search for TT 910 int tt=int(tmp.find("<TT>")),ttend=tt; 911 if (tt>=0 && tt+6<s){ 912 for (ttend+=4;ttend<s;++ttend){ 913 if (tmp[ttend]=='<'){ 914 ttend +=5; 915 break; 916 } 917 tts += tmp[ttend]; 918 } 919 mtt.insert(pair<string,string>(tts,hrefs)); 920 mall.insert(pair<string,string>(tts,hrefs)); 921 tmp=tmp.substr(0,tt)+tmp.substr(ttend,tmp.size()-ttend); 922 } 923 // add href for all normal words 924 s=int(tmp.size()); 925 int j=hrefend+1; 926 for (;j<s;){ 927 // read word 928 int pos=int(tmp.find(' ',j)); 929 if (pos>j && pos<s){ 930 // add it 931 string tmpins(tmp.substr(j,pos-j)); 932 mall.insert(pair<string,string>(tmpins,hrefs)); 933 } 934 if (pos==-1){ 935 string tmpins(tmp.substr(j,s-j)); 936 mall.insert(pair<string,string>(tmpins,hrefs)); 937 break; 938 } 939 j=pos+1; 940 } 941 } // end else is_index 942 } 943 return false; 944 } 945 946 static const string subdir_strings[]={"cascmd","casgeo","casrouge","cassim","castor","tutoriel","casinter","casexo","cascas"}; 947 static const int subdir_taille=sizeof(subdir_strings)/sizeof(string); equalposcomp(const string * tab,const string & s)948 static int equalposcomp(const string * tab,const string & s){ 949 int i=int(s.size())-1; 950 for (;i>=0;--i){ 951 if (s[i]=='/') 952 break; 953 } 954 ++i; 955 string t=s.substr(i,s.size()-i); 956 i=int(t.size())-1; 957 for (;i>=0;--i){ 958 if (t[i]=='_') 959 t=t.substr(0,i); 960 } 961 for (i=0;i<subdir_taille;++i){ 962 // cerr << *(tab+i) << " " << t << endl; 963 if (*(tab+i)==t) 964 return i+1; 965 } 966 return 0; 967 } 968 969 #if ! (defined VISUALC || defined BESTA_OS || defined FREERTOS || defined NSPIRE || defined FXCG || defined NSPIRE_NEWLIB || defined(KHICAS)) 970 #if defined WIN32 || !defined DT_DIR dir_select(const struct dirent * d)971 static int dir_select (const struct dirent *d){ 972 string s(d->d_name); 973 // cerr << s << endl; 974 int t=s.size(); 975 if (s[t-1]=='\\'){ 976 return s!="." && s!=".."; 977 } 978 if (t<9) 979 return 0; 980 if (s[t-1]=='l'){ 981 s=s.substr(0,t-1); 982 --t; 983 } 984 if (t>9) 985 s=s.substr(t-9,9); 986 return s=="index.htm"; 987 } 988 #else 989 // __APPLE_CC__ == 5666 on Mac OS X 10.6, 5658 on geogebra build system OS X 10.8 990 // should check __APPLE__ OS X version instead! 991 #if ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED)&& __MAC_OS_X_VERSION_MAX_ALLOWED< 1080 ) || ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED)&& __IPHONE_OS_VERSION_MAX_ALLOWED< 60100 ) || ( defined(__OpenBSD__)&& OpenBSD<201905) || ( defined(__FreeBSD_version)&& __FreeBSD_version<800501) dir_select(struct dirent * d)992 static int dir_select (struct dirent *d){ 993 #else 994 static int dir_select (const struct dirent *d){ 995 #endif 996 string s(d->d_name); 997 if (d->d_type==DT_DIR || equalposcomp(subdir_strings,s)){ 998 return s!="." && s!=".."; 999 } 1000 int t=s.size(); 1001 if (t<9) 1002 return 0; 1003 if (s[t-1]=='l'){ 1004 s=s.substr(0,t-1); 1005 --t; 1006 } 1007 if (t>9) 1008 s=s.substr(t-9,9); 1009 return s=="index.htm"; 1010 } 1011 #endif 1012 #endif // visualc 1013 1014 void find_all_index(const std::string & subdir,multimap<std::string,std::string> & mtt,multimap<std::string,std::string> & mall){ 1015 #if defined GNUWINCE || defined __MINGW_H || defined __ANDROID__ || defined EMCC || defined NSPIRE_NEWLIB || defined FXCG || defined KHICAS 1016 return; 1017 #else 1018 // cerr << "HTML help Scanning " << subdir << endl; 1019 DIR *dp; 1020 struct dirent *ep; 1021 1022 dp = opendir (subdir.c_str()); 1023 if (dp != NULL){ 1024 string s; 1025 int t; 1026 while ( (ep = readdir (dp)) ){ 1027 s=ep->d_name; 1028 t=s.size(); 1029 if (t>5 && s.substr(t-4,4)=="html") 1030 html_vall.push_back(subdir+s); 1031 } 1032 closedir (dp); 1033 } 1034 1035 struct dirent **eps; 1036 int n; 1037 #if defined APPLE_SMART || defined NO_SCANDIR 1038 n =-1; 1039 #else 1040 n = scandir (subdir.c_str(), &eps, dir_select, alphasort); 1041 #endif 1042 if (n >= 0){ 1043 bool index_done=false; 1044 int cnt; 1045 for (cnt = -1; cnt < n; ++cnt){ 1046 string s; 1047 if (cnt==-1) 1048 s="index.html"; 1049 else 1050 s=eps[cnt]->d_name; 1051 s= subdir+s; 1052 #if defined WIN32 || !defined DT_DIR 1053 int t=s.size(); 1054 if (s[t-1]=='\\') 1055 find_all_index(s+"/",mtt,mall); 1056 else { 1057 if (!index_done) 1058 index_done=find_index(subdir,s,mtt,mall); 1059 } 1060 #else 1061 unsigned char type=cnt>=0?eps[cnt]->d_type:0; 1062 if (type==DT_DIR || equalposcomp(subdir_strings,s)) 1063 find_all_index(s+"/",mtt,mall); 1064 else { 1065 if (!index_done) 1066 index_done=find_index(subdir,s,mtt,mall); 1067 } 1068 #endif 1069 } 1070 } 1071 #endif // GNUWINCE 1072 } 1073 1074 // Return all HTML nodes refered to s in mtt 1075 std::vector<std::string> html_help(multimap<std::string,std::string> & mtt,const std::string & s){ 1076 vector<string> v; 1077 multimap<string,string>::const_iterator it=mtt.lower_bound(s),itend=mtt.upper_bound(s); 1078 for (;it!=itend;++it){ 1079 v.push_back(it->second); 1080 } 1081 return v; 1082 } 1083 1084 string xcasroot_dir(const char * arg){ 1085 string xcasroot; 1086 if (getenv("XCAS_ROOT")){ 1087 xcasroot=string(getenv("XCAS_ROOT")); 1088 if (xcasroot.empty()) 1089 xcasroot="/"; 1090 if (xcasroot[xcasroot.size()-1]!='/') 1091 xcasroot+='/'; 1092 } 1093 else { 1094 xcasroot=arg; 1095 int xcasroot_size=int(xcasroot.size())-1; 1096 for (;xcasroot_size>=0;--xcasroot_size){ 1097 if (xcasroot[xcasroot_size]=='/') 1098 break; 1099 } 1100 if (xcasroot_size>0) 1101 xcasroot=xcasroot.substr(0,xcasroot_size)+"/"; 1102 else { 1103 if (access("/usr/bin/xcas",R_OK)==0) 1104 xcasroot="/usr/bin/"; 1105 else { 1106 #ifdef __APPLE__ 1107 if (access("/Applications/usr/bin/xcas",R_OK)==0) 1108 xcasroot="/Applications/usr/bin"; 1109 #else 1110 if (access("/usr/local/bin/xcas",R_OK)==0) 1111 xcasroot="/usr/local/bin/"; 1112 #endif 1113 else 1114 xcasroot="./"; 1115 } 1116 } 1117 } 1118 // ofstream of("/tmp/xcasroot"); 1119 // of << xcasroot << endl; 1120 return xcasroot; 1121 } 1122 1123 // extern int debug_infolevel; 1124 static bool get_index_from_cache(const char * filename, multimap<string,string> & multi,bool verbose){ 1125 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1126 char * buf = new char[BUFFER_SIZE]; 1127 #else 1128 char buf[BUFFER_SIZE]; 1129 #endif 1130 ifstream if_mtt(filename); 1131 int n=0; 1132 while (if_mtt && !if_mtt.eof()){ 1133 if_mtt.getline(buf,BUFFER_SIZE,char(0xa4)); // was '�', utf8 not compatible, octal \244 1134 if (!if_mtt || if_mtt.eof()){ 1135 if (verbose) 1136 cerr << "// Read " << n << " entries from cache " << filename << endl; 1137 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1138 delete [] buf; 1139 #endif 1140 return true; 1141 } 1142 string first(buf); 1143 if_mtt.getline(buf,BUFFER_SIZE,char(0xa4)); 1144 if (!if_mtt || if_mtt.eof()){ 1145 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1146 delete [] buf; 1147 #endif 1148 return false; 1149 } 1150 multi.insert(pair<string,string>(first,buf)); 1151 if (!(n%100)){ // check every 100 links if link exists 1152 first=buf; 1153 int l=int(first.size()),j; 1154 char ch=0; 1155 for (j=l-1;j>=0;--j){ 1156 ch=first[j]; 1157 if (ch=='#' || ch=='/') 1158 break; 1159 } 1160 if (j>0 && ch=='#') 1161 first=first.substr(0,j); 1162 if (access(first.c_str(),R_OK)){ 1163 multi.clear(); 1164 cerr << "Wrong cache! " << filename << endl; 1165 if_mtt.close(); 1166 #if !defined RTOS_THREADX && !defined BESTA_OS && !defined FREERTOS 1167 if (unlink(filename)==-1) 1168 cerr << "You don't have write permissions on " << filename <<".\nYou must ask someone who has write permissions to remove " << filename << endl; 1169 else 1170 cerr << "Cache file "<< filename << " has been deleted" << endl; 1171 #endif 1172 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1173 delete [] buf; 1174 #endif 1175 return false; 1176 } 1177 } 1178 ++n; 1179 if_mtt.getline(buf,BUFFER_SIZE,'\n'); 1180 } 1181 if (verbose) 1182 cerr << "// Read " << n << " entries from cache " << filename ; 1183 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1184 delete [] buf; 1185 #endif 1186 return true; 1187 } 1188 1189 static bool get_index_from_cache(const char * filename, vector<string> & multi,bool verbose){ 1190 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1191 char * buf = new char[BUFFER_SIZE]; 1192 #else 1193 char buf[BUFFER_SIZE]; 1194 #endif 1195 ifstream if_mtt(filename); 1196 int n=0; 1197 while (if_mtt && !if_mtt.eof()){ 1198 if_mtt.getline(buf,BUFFER_SIZE,char(0xa4)); 1199 if (!if_mtt || if_mtt.eof()){ 1200 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1201 delete [] buf; 1202 #endif 1203 if (verbose) 1204 cerr << "// Read " << n << " entries from cache " << filename << endl; 1205 return true; 1206 } 1207 multi.push_back(buf); 1208 ++n; 1209 if_mtt.getline(buf,BUFFER_SIZE,'\n'); 1210 } 1211 #if defined VISUALC || defined BESTA_OS || defined FREERTOS 1212 delete [] buf; 1213 #endif 1214 if (verbose) 1215 cerr << "// Read " << n << " entries from cache " << filename ; 1216 return true; 1217 } 1218 1219 string html_help_init(const char * arg,int language,bool verbose,bool force_rebuild){ 1220 string xcasroot=xcasroot_dir(arg); 1221 // HTML online help 1222 string html_help_dir=xcasroot+"doc/"; 1223 if (access(html_help_dir.c_str(),R_OK)){ 1224 #ifdef __APPLE__ 1225 if (!access("/Applications/usr/bin/icas",R_OK)) 1226 html_help_dir="/Applications/usr/share/giac/doc/"; 1227 #else 1228 if (!access("/usr/bin/xcas",R_OK)) 1229 html_help_dir="/usr/share/giac/doc/"; 1230 #endif 1231 else { 1232 if (!access("/usr/local/bin/xcas",R_OK)) 1233 html_help_dir="/usr/local/share/giac/doc/"; 1234 } 1235 } 1236 if (access(html_help_dir.c_str(),R_OK) && xcasroot.size()>4 && xcasroot.substr(xcasroot.size()-4,4)=="bin/") 1237 html_help_dir=xcasroot.substr(0,xcasroot.size()-4)+"share/giac/doc/"; 1238 if (access(html_help_dir.c_str(),R_OK)) 1239 cerr << "Unable to open HTML doc directory " << html_help_dir << endl; 1240 html_help_dir += find_lang_prefix(language); 1241 #ifdef WIN32 1242 string html_help_dir_save=html_help_dir; 1243 html_help_dir +="cascmd_"+find_lang_prefix(giac::language(context0)); // temporary workaround, for win archive copy doc/fr/html_vall to doc/fr/cascmd_fr/html_vall and change path 1244 #endif 1245 html_mtt.clear(); 1246 html_mall.clear(); 1247 html_vall.clear(); 1248 // Get indices from file cache if it exists 1249 if (!force_rebuild && !access((html_help_dir+"html_mtt").c_str(),R_OK) && !access((html_help_dir+"html_mall").c_str(),R_OK) && !access((html_help_dir+"html_vall").c_str(),R_OK)){ 1250 if (get_index_from_cache((html_help_dir+"html_mtt").c_str(),html_mtt,verbose)&& 1251 get_index_from_cache((html_help_dir+"html_mall").c_str(),html_mall,verbose)&& 1252 get_index_from_cache((html_help_dir+"html_vall").c_str(),html_vall,verbose) ) 1253 return html_help_dir; 1254 } 1255 find_all_index(html_help_dir,html_mtt,html_mall); 1256 #ifdef WIN32 1257 for (unsigned i=0;i<sizeof(subdir_strings)/sizeof(const string);++i){ 1258 find_all_index(html_help_dir_save+subdir_strings[i]+"/",html_mtt,html_mall); 1259 } 1260 #endif 1261 // Write all indices in a file cache 1262 ofstream of_mtt((html_help_dir+"html_mtt").c_str()); 1263 multimap<string,string>::const_iterator it=html_mtt.begin(),itend=html_mtt.end(); 1264 for (;it!=itend;++it) 1265 of_mtt << it->first << char(0xa4) << it->second << char(0xa4) << endl; 1266 of_mtt.close(); 1267 ofstream of_mall((html_help_dir+"html_mall").c_str()); 1268 it=html_mall.begin();itend=html_mall.end(); 1269 for (;it!=itend;++it) 1270 of_mall << it->first << char(0xa4) << it->second << char(0xa4) << endl; 1271 of_mall.close(); 1272 ofstream of_vall((html_help_dir+"html_vall").c_str()); 1273 vector<string>::const_iterator st=html_vall.begin(),stend=html_vall.end(); 1274 for (;st!=stend;++st) 1275 of_vall << *st << char(0xa4) << endl; 1276 of_vall.close(); 1277 /* 1278 if (debug_infolevel){ 1279 vector<string>::const_iterator it=html_vall.begin(),itend=html_vall.end(); 1280 for (;it!=itend;++it) 1281 cerr << *it << endl; 1282 } 1283 */ 1284 return html_help_dir; 1285 } 1286 1287 static bool multigrep(FILE * f,const string & s){ 1288 int l=int(s.size()); 1289 // find spaces 1290 string tmp; 1291 vector<string> vs; 1292 for (int i=0;i<l;++i){ 1293 if (s[i]==' '){ 1294 if (!tmp.empty()) 1295 vs.push_back(tmp); 1296 tmp=""; 1297 } 1298 else 1299 tmp+=s[i]; 1300 } 1301 if (!tmp.empty()) 1302 vs.push_back(tmp); 1303 l=int(vs.size()); 1304 if (!f || !l) 1305 return false; 1306 char c; 1307 for (tmp="";;){ 1308 if (feof(f) || ferror(f)){ 1309 return false; 1310 } 1311 c=fgetc(f); 1312 if (c==char(0xc3)){ 1313 if (feof(f) || ferror(f)) 1314 return false; 1315 unsigned code=fgetc(f); 1316 switch (code){ 1317 case 0xa8: case 0xa9: case 0xaa: 1318 c='e'; 1319 break; 1320 case 0xa0: case 0xa1: case 0xa2: 1321 c='a'; 1322 break; 1323 case 0xae: case 0xaf: 1324 c='i'; 1325 break; 1326 case 0xb4: 1327 c='o'; 1328 break; 1329 case 0xb9: case 0xbb: 1330 c='u'; 1331 break; 1332 case 0xa7: 1333 c='c'; 1334 break; 1335 } 1336 } 1337 c=tolower(c); 1338 if (c=='&'){ 1339 c=fgetc(f); 1340 if (c=='#'){ 1341 unsigned code=0,base=10; 1342 for (;;){ 1343 if (feof(f) || ferror(f)) 1344 return false; 1345 c=fgetc(f); 1346 if (c=='x' || c=='X') 1347 base=16; 1348 if (c=='o' || c=='O') 1349 base=8; 1350 if (c!=';'){ 1351 if (base!=16) 1352 code = code*base+c-'0'; 1353 else { 1354 if (c>='A' && c<='F') 1355 code = code*base + c-'A'+10; 1356 if (c>='a' && c<='f') 1357 code = code*base + c-'a'+10; 1358 if (c>='0' && c<='9') 1359 code = code*base + c-'0'; 1360 } 1361 } 1362 else{ 1363 switch (code){ 1364 case 0xe8: case 0xe9: case 0xea: 1365 c='e'; 1366 break; 1367 case 0xe0: case 0xe2: 1368 c='a'; 1369 break; 1370 case 0xf4: 1371 c='o'; 1372 break; 1373 case 0xf9: case 0xfb: 1374 c='u'; 1375 break; 1376 case 0xe7: 1377 c='c'; 1378 break; 1379 case 238: 1380 c='i'; 1381 break; 1382 } 1383 break; 1384 } 1385 } 1386 } 1387 } 1388 if (c==' '){ 1389 if (!tmp.empty()){ // search tmp in vs 1390 unsigned tmpl=unsigned(tmp.size()),tmpvs; 1391 for (int i=0;i<l;++i){ 1392 if ( (tmpvs=unsigned(vs[i].size()))<=tmpl && tmp.substr(0,tmpvs)==vs[i]){ 1393 vs.erase(vs.begin()+i); 1394 --l; 1395 if (l<=0) 1396 return true; 1397 } 1398 } 1399 } 1400 tmp=""; 1401 } 1402 else 1403 tmp+=c; 1404 } 1405 } 1406 1407 bool grep(FILE * f,const string & s){ 1408 int l=int(s.size()); 1409 int pos=0; 1410 if (!f || !l) 1411 return false; 1412 char c0=tolower(s[0]),c; 1413 for (;;){ 1414 if (feof(f) || ferror(f)){ 1415 return false; 1416 } 1417 c=tolower(fgetc(f)); 1418 if (c==tolower(s[pos])){ 1419 ++pos; 1420 if (pos==l){ 1421 return true; 1422 } 1423 } 1424 else { 1425 if (c==c0) 1426 pos=1; 1427 else 1428 pos=0; 1429 } 1430 } 1431 } 1432 1433 bool grep(const string & filename,const string & s){ 1434 FILE * f=fopen(filename.c_str(),"r"); 1435 bool res=multigrep(f,s); 1436 if (f) 1437 fclose(f); 1438 return res; 1439 } 1440 #endif // RTOS_THREADX 1441 1442 // static char otherchars[]="_.~������������������������������������������������������������������������������������������������"; 1443 1444 bool isalphan(char ch){ 1445 if (ch>='0' && ch<='9') 1446 return true; 1447 if (ch>='a' && ch<='z') 1448 return true; 1449 if (ch>='A' && ch<='Z') 1450 return true; 1451 if (unsigned(ch)>128) 1452 return true; 1453 if (ch=='_' || ch=='.' || ch=='~') 1454 return true; 1455 /* 1456 char * ptr=otherchars; 1457 for (;*ptr;++ptr){ 1458 if (ch==*ptr) 1459 return true; 1460 } 1461 */ 1462 return false; 1463 } 1464 1465 std::string unlocalize(const std::string & s){ 1466 std::string res,tmp; 1467 int ss=int(s.size()); 1468 std::map<std::string,std::string>::const_iterator it,itend=lexer_localization_map().end(); 1469 int mode=0; // 1 if inside a string 1470 for (int i=0;;++i){ 1471 char ch=s[i]; 1472 if (mode){ 1473 if (ch=='"'){ 1474 if (res.empty() || res[res.size()-1]!='\\') 1475 mode=0; 1476 } 1477 res += ch; 1478 if (i==ss) 1479 break; 1480 continue; 1481 } 1482 if (i<ss && isalphan(ch)) 1483 tmp += ch; 1484 else { // search if tmp is in lexer_localization_map 1485 it=lexer_localization_map().find(tmp); 1486 if (it!=itend) 1487 tmp = it->second; // it is -> we must translate to giac 1488 res += tmp; 1489 tmp = ""; 1490 if (ch=='"'){ 1491 if (res.empty() || res[res.size()-1]!='\\') 1492 mode=1; 1493 } 1494 if (i<ss) 1495 res += ch; 1496 else 1497 break; 1498 } 1499 } 1500 if (mode==1) 1501 return unlocalize(s+'"'); 1502 return res; 1503 } 1504 1505 std::string localize(const std::string & s,int language){ 1506 std::string res,tmp; 1507 int ss=int(s.size()); 1508 int mode=0; // 1 if inside a string 1509 std::multimap<std::string,localized_string>::const_iterator it0,it,itend,backend=back_lexer_localization_map().end(); 1510 for (int i=0;;++i){ 1511 char ch=s[i]; 1512 if (mode){ 1513 if (ch=='"'){ 1514 if (res.empty() || res[res.size()-1]!='\\') 1515 mode=0; 1516 } 1517 res += ch; 1518 if (i==ss) 1519 break; 1520 continue; 1521 } 1522 if (i<ss && isalphan(s[i])) 1523 tmp += s[i]; 1524 else { // search if tmp is in back_lexer_localization_map() 1525 it0=it=back_lexer_localization_map().find(tmp); 1526 itend=back_lexer_localization_map().upper_bound(tmp); 1527 if (it!=backend){ 1528 for (;it!=itend;++it){ 1529 if (it->second.language==language){ 1530 tmp = it->second.chaine; 1531 break; 1532 } 1533 } 1534 if (it==itend) 1535 tmp = it0->second.chaine; 1536 } 1537 res += tmp; 1538 tmp = ""; 1539 if (ch=='"'){ 1540 if (res.empty() || res[res.size()-1]!='\\') 1541 mode=1; 1542 } 1543 if (i<ss) 1544 res += s[i]; 1545 else 1546 break; 1547 } 1548 } 1549 return res; 1550 } 1551 1552 #ifndef NO_NAMESPACE_GIAC 1553 } // namespace giac 1554 #endif // ndef NO_NAMESPACE_GIAC 1555