PageRenderTime 66ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/archive/lkcdutils/libsial/sial_util.c

#
C | 811 lines | 593 code | 160 blank | 58 comment | 143 complexity | 77ca4893b5774cb034b8e9269c8c0c7a MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. * Copyright 2001 Silicon Graphics, Inc. All rights reserved.
  3. */
  4. #include "sial.h"
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <curses.h>
  8. #include <term.h>
  9. #include <termio.h>
  10. #include <ctype.h>
  11. #include <stdarg.h>
  12. #include <malloc.h>
  13. #include <limits.h>
  14. #include <sys/mman.h>
  15. #include <sys/types.h>
  16. #include <stdlib.h>
  17. #include <regex.h>
  18. #include <ctype.h>
  19. static FILE *ofile=0;
  20. static int cols=25;
  21. static char *bold_on, *bold_off;
  22. static void
  23. sial_getwinsize(void)
  24. {
  25. struct winsize w;
  26. if (ioctl (fileno(ofile), TIOCGWINSZ, &w) == 0)
  27. {
  28. cols=w.ws_col;
  29. }
  30. else /* use ENV */
  31. {
  32. char *ewidth;
  33. if ((ewidth = getenv ("COLUMNS")))
  34. cols = atoi (ewidth);
  35. /* use what's in terminfo */
  36. if (cols <= 0)
  37. cols = tigetnum ("co");
  38. }
  39. if(cols <= 10) cols=10;
  40. if(cols > 80) cols=80;
  41. }
  42. void
  43. sial_setofile(void * f)
  44. {
  45. int out;
  46. int ret;
  47. char *term;
  48. ofile=(FILE *)f;
  49. bold_on="";
  50. bold_off="";
  51. cols=80;
  52. out=fileno(ofile);
  53. if(isatty(out))
  54. {
  55. if(!(term = getenv ("TERM"))) term="dumb";
  56. if(setupterm(term, out, &ret)!=ERR)
  57. {
  58. bold_on=tigetstr("bold");
  59. if(!bold_on) bold_on="";
  60. bold_off=tigetstr("sgr0");
  61. if(!bold_off) bold_off="";
  62. }
  63. sial_getwinsize();
  64. }
  65. }
  66. void *
  67. sial_getofile(void)
  68. {
  69. return ofile;
  70. }
  71. /*
  72. Output a line of text to the screen with line wrap
  73. and escape sequence.
  74. */
  75. #define ESC '<'
  76. #define ESC2 '>'
  77. static int
  78. sial_tabs(int tabs, char *t, int lf)
  79. {
  80. int i;
  81. if(lf) fprintf(ofile, "\n");
  82. for(i=0;i <tabs; i++) fprintf(ofile, t);
  83. return tabs*4;
  84. }
  85. void
  86. sial_format(int tabs, char *str)
  87. {
  88. char *t=" ";
  89. char *p;
  90. int n;
  91. int mode=0;
  92. n=sial_tabs(tabs, t, 0);
  93. sial_getwinsize();
  94. for(p=str; *p; p++) {
  95. /* check for escape */
  96. if(!mode && *p == ESC && *(p+1) && *(p+1) == ESC) {
  97. fprintf(ofile, "%s", bold_on);
  98. p++;
  99. mode=1;
  100. } else if(mode && *p == ESC2 && *(p+1) && *(p+1) == ESC2) {
  101. fprintf(ofile, "%s", bold_off);
  102. p++;
  103. mode=0;
  104. } else if(*p==' ' || *p=='\t' ) {
  105. char *p2;
  106. int wl;
  107. for(p2=p+1; *p2 && *p2 != ' ' && *p2 != '\t'; p2++);
  108. wl=p2-p-1;
  109. if(wl > cols) {
  110. char *p3=p+(cols-n-1);
  111. char c=*p3;
  112. char c2=*(p3+1);
  113. *p3='-';
  114. *(p3+1)='\0';
  115. fprintf(ofile, "%s", p);
  116. *p3=c;
  117. *(p3+1)=c2;
  118. n=sial_tabs(tabs, t, 0);
  119. } else if(n + (p2-p) >= cols) {
  120. n=sial_tabs(tabs, t, 1);
  121. } else {
  122. fprintf(ofile, " ");
  123. n++;
  124. }
  125. } else if(*p=='\n') {
  126. n=sial_tabs(tabs, t, 1);
  127. } else {
  128. fprintf(ofile, "%c", *p);
  129. n++;
  130. }
  131. }
  132. }
  133. void
  134. sial_msg(char *fmt, ...)
  135. {
  136. va_list ap;
  137. va_start(ap, fmt);
  138. vfprintf(ofile, fmt, ap);
  139. va_end(ap);
  140. }
  141. void
  142. sial_freenode(node_t *n)
  143. {
  144. n->free(n->data);
  145. sial_free(n);
  146. }
  147. int lineno=1, lastline=1;
  148. int col=1;
  149. static char *filename=0;
  150. static char *lastfile=0;
  151. void
  152. sial_setlastfile(char *fname, int line)
  153. {
  154. if(!fname) return;
  155. if(lastfile) sial_free(lastfile);
  156. lastfile=sial_strdup(fname);
  157. lastline=line;
  158. }
  159. void
  160. sial_rstpos(void)
  161. {
  162. lineno=1;
  163. col=1;
  164. /* do not free filename */
  165. filename=0;
  166. }
  167. void
  168. sial_setpos(srcpos_t *p)
  169. {
  170. p->line=lineno;
  171. p->col=col;
  172. p->file=filename;
  173. }
  174. /* set the current position */
  175. void
  176. sial_curpos(srcpos_t *p, srcpos_t *s)
  177. {
  178. if(s) {
  179. s->line=lineno;
  180. s->col=col;
  181. s->file=filename;
  182. }
  183. lineno=p->line;
  184. col=p->col;
  185. filename=p->file;
  186. }
  187. int
  188. sial_line(int inc){ return lineno+=inc; }
  189. int
  190. sial_col(int inc) { return col+=inc; }
  191. char *
  192. sial_filename(void) { return filename; }
  193. /*
  194. This function scans a printf() fmt string and transaletes the %p
  195. to %08x or %016x depending on the pointer size of the object image.
  196. We also substiture %> for 8 spaces if the pointer size is 4 bytes, this
  197. permits easy allignment of output on either 32 or 64 bit images.
  198. ex:
  199. Proc %> pid ppid
  200. %p %3d %3d
  201. In this case the %> alligns the pid with it's corresponding value_t
  202. in the next line of output.
  203. We also process the '?' format which will be set to match the
  204. corresponding value_t type.
  205. Also, format versus argument type validation is performed.
  206. */
  207. /*
  208. Printf formats have the form :
  209. %3$-*3$.*4$lld
  210. %20x
  211. %08x
  212. %-08.8f
  213. */
  214. /* these are the buildin blocks for a regex matching formats */
  215. #define F_POSP "([0-9]+\\$)*"
  216. #define F_FLGS "([-'+ #0]*)"
  217. #define F_WARG "(\\*([0-9]+\\$)*){0,1}"
  218. #define F_WIDTH "([0-9]*)"
  219. #define F_PREC "((\\.(\\*([0-9]+\\$)*)*([0-9]*))*)"
  220. #define F_SIZE "([hlL]*)"
  221. #define F_FMT "([diouxXfeEgGcCsSpn?>]{1})"
  222. #define FMTREG F_POSP""F_FLGS""F_WARG""F_WIDTH""F_PREC""F_SIZE""F_FMT
  223. #define M_POSP 1
  224. #define M_FLAGS 2
  225. #define M_WIDTHARG 3
  226. #define M_WIDTDIGITS 4
  227. #define M_WIDTH 5
  228. #define M_PRECARG 8
  229. #define M_PRECDIGITS 9
  230. #define M_PREC 10
  231. #define M_SIZE 11
  232. #define M_FMT 12
  233. #define NMATCH 16
  234. static int addit[]={M_FLAGS,M_WIDTHARG,M_WIDTH,M_PRECARG,M_PREC,M_SIZE};
  235. #define ptrto(idx) (matches[idx].rm_so==matches[idx].rm_eo?0:(pi+matches[idx].rm_so))
  236. #define matchlen(idx) (matches[(idx)].rm_eo-matches[(idx)].rm_so)
  237. void sial_error(char *fmt, ...);
  238. static int
  239. chkforint(char *p, value_t **vals, int *curarg)
  240. {
  241. int pos=-1;
  242. if(!p) return -1;
  243. /* a single star ? */
  244. if(isdigit(p[1])) {
  245. if(sscanf(p+1, "%d", &pos)!=1) {
  246. return pos;
  247. }
  248. pos--;
  249. } else {
  250. pos=*curarg;
  251. *curarg=(*curarg)+1;
  252. }
  253. if(pos < BT_MAXARGS && vals[pos] && vals[pos]->type.type == V_BASE) return pos;
  254. sial_error("Expected 'integer' type for arg%d", pos+1);
  255. return -1;
  256. }
  257. #define pushval(val, s, sig) ( \
  258. sig ? \
  259. ( \
  260. (s==8) ? \
  261. (val)->v.sll \
  262. : ( \
  263. (s==4) ? \
  264. (val)->v.sl \
  265. : ( \
  266. (s==2) ? \
  267. (val)->v.ss \
  268. :( \
  269. (s==1) ? \
  270. (val)->v.sc \
  271. :( \
  272. sial_error("Oops pushval"),1 \
  273. ) \
  274. ) \
  275. ) \
  276. ) \
  277. ) : ( \
  278. (s==8) ? \
  279. (val)->v.ull \
  280. : ( \
  281. (s==4) ? \
  282. (val)->v.ul \
  283. : ( \
  284. (s==2) ? \
  285. (val)->v.us \
  286. :( \
  287. (s==1) ? \
  288. (val)->v.uc \
  289. :( \
  290. sial_error("Oops pushval"),1 \
  291. ) \
  292. ) \
  293. ) \
  294. ) \
  295. ) \
  296. )
  297. static char *
  298. add_fmt(int len, char *s, char *onefmt, int ppos, int wpos, int posarg, value_t **vals)
  299. {
  300. int size=(vals[posarg]->type.type == V_REF ? sial_defbsize(): vals[posarg]->type.size);
  301. int sign=(vals[posarg]->type.type == V_REF ? 0 : sial_issigned(vals[posarg]->type.typattr));
  302. if(vals[posarg]->type.type == V_STRING) {
  303. if(wpos>=0 && ppos<0)
  304. s+=snprintf(s, len, onefmt
  305. , (int)sial_getval(vals[wpos])
  306. , vals[posarg]->v.data);
  307. else if(wpos<0 && ppos>=0)
  308. s+=snprintf(s, len, onefmt
  309. , (int)sial_getval(vals[ppos])
  310. , vals[posarg]->v.data);
  311. else if(wpos>=0 && ppos>=0)
  312. s+=snprintf(s, len, onefmt
  313. , (int)sial_getval(vals[wpos])
  314. , (int)sial_getval(vals[ppos])
  315. , vals[posarg]->v.data);
  316. else s+=snprintf(s, len, onefmt
  317. , vals[posarg]->v.data);
  318. } else {
  319. #if defined(__s390x__) || defined(__s390__)
  320. if(wpos>=0 && ppos<0)
  321. s+=snprintf(s, len, onefmt
  322. , (int)sial_getval(vals[wpos])
  323. , (unsigned long)pushval(vals[posarg], size, sign));
  324. else if(wpos<0 && ppos>=0)
  325. s+=snprintf(s, len, onefmt
  326. , (int)sial_getval(vals[ppos])
  327. , (unsigned long)pushval(vals[posarg], size, sign));
  328. else if(wpos>=0 && ppos>=0)
  329. s+=snprintf(s, len, onefmt
  330. , (int)sial_getval(vals[wpos])
  331. , (int)sial_getval(vals[ppos])
  332. , (unsigned long) pushval(vals[posarg], size, sign));
  333. else s+=snprintf(s, len, onefmt
  334. , (unsigned long) pushval(vals[posarg], size, sign));
  335. #else
  336. if(wpos>=0 && ppos<0)
  337. s+=snprintf(s, len, onefmt
  338. , (int)sial_getval(vals[wpos])
  339. , pushval(vals[posarg], size, sign));
  340. else if(wpos<0 && ppos>=0)
  341. s+=snprintf(s, len, onefmt
  342. , (int)sial_getval(vals[ppos])
  343. , pushval(vals[posarg], size, sign));
  344. else if(wpos>=0 && ppos>=0)
  345. s+=snprintf(s, len, onefmt
  346. , (int)sial_getval(vals[wpos])
  347. , (int)sial_getval(vals[ppos])
  348. , pushval(vals[posarg], size, sign));
  349. else s+=snprintf(s, len, onefmt
  350. , pushval(vals[posarg], size, sign));
  351. #endif
  352. }
  353. return s;
  354. }
  355. static char *
  356. sial_ptr(char *fmt, value_t **vals)
  357. {
  358. int len=strlen(fmt)+100;
  359. char *nfmt=sial_alloc(len),*ni=nfmt;
  360. char *onefmt=sial_alloc(100), *onei=onefmt;
  361. char *p=fmt;
  362. char last=' ';
  363. int curarg=0;
  364. #define NBYTES (len-(nfmt-ni))
  365. while(*p) {
  366. if(*p=='%') {
  367. static regex_t preg;
  368. static int done=0;
  369. regmatch_t matches[NMATCH];
  370. if(!done) {
  371. regcomp(&preg, FMTREG, REG_EXTENDED);
  372. done=1;
  373. }
  374. /* build a new format translation */
  375. onefmt=onei;
  376. *onefmt++=*p++;
  377. /* if the returned pointer is (char*)-1 or NULL then something is wrong */
  378. if(!regexec(&preg, p, NMATCH, matches, 0)) {
  379. int i, n=matches[0].rm_eo-1;
  380. int posarg, wpos, ppos;
  381. char *pi=p; /* save p for ptrto() macro */
  382. /* check that the width and precision field args point
  383. to a int value_t. If they were used */
  384. wpos=chkforint(ptrto(M_WIDTHARG), vals, &curarg);
  385. ppos=chkforint(ptrto(M_PRECARG), vals, &curarg);
  386. /* argument position was specfified ? */
  387. if(ptrto(M_POSP)) {
  388. /* we work from 0-n, printf works from 1-n */
  389. if(sscanf(ptrto(M_POSP), "%d", &posarg)==1) posarg--;
  390. if(posarg >= BT_MAXARGS || !vals[posarg]) {
  391. sial_error("Invalid arg position specified [%d]", posarg+1);
  392. }
  393. } else posarg=curarg++;
  394. /* jump over the format spec in the original */
  395. p+=n;
  396. #if 0
  397. for(i=0;i<NMATCH;i++) {
  398. char buf[40];
  399. if(ptrto(i)) {
  400. int n=matchlen(i);
  401. strncpy(buf, pi+matches[i].rm_so, n);
  402. buf[n]='\0';
  403. printf("match[%d]=[%s]\n", i, buf);
  404. }
  405. }
  406. #endif
  407. /* copy all format specs to destination except fmt */
  408. for(i=0;i<sizeof(addit)/sizeof(addit[0]);i++) {
  409. switch(addit[i]) {
  410. case M_WIDTHARG:
  411. if(wpos >=0 ){
  412. *onefmt++='*';
  413. } else goto def;
  414. break;
  415. case M_PRECARG:
  416. if(ppos >=0 ){
  417. *onefmt++='.';
  418. *onefmt++='*';
  419. } else goto def;
  420. break;
  421. case M_PREC:
  422. if(ptrto(addit[i])) *onefmt++='.';
  423. goto def;
  424. default:
  425. def:
  426. if(ptrto(addit[i])) {
  427. strcpy(onefmt, ptrto(addit[i]));
  428. onefmt+=matchlen(addit[i]);
  429. }
  430. }
  431. }
  432. if(*p=='p') {
  433. ref:
  434. /* if user overrides anything don't do nothing */
  435. if(ptrto(M_FLAGS)||ptrto(M_WIDTH)||ptrto(M_WIDTHARG)||ptrto(M_PREC)||ptrto(M_PRECARG)||ptrto(M_SIZE)) {
  436. *onefmt++='p';
  437. } else {
  438. if(sial_defbsize()==8) {
  439. strcpy(onefmt, "016llx");
  440. onefmt+=6;
  441. } else {
  442. strcpy(onefmt, "08x");
  443. onefmt+=3;
  444. }
  445. }
  446. *onefmt='\0';
  447. p++;
  448. nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals);
  449. } else if(*p=='>') {
  450. nfmt--;
  451. if(sial_defbsize()==8) {
  452. int i;
  453. for(i=0;i<8;i++) *nfmt++=last;
  454. }
  455. p++;
  456. } else if(*p=='?') {
  457. /* put the proper format for the user */
  458. if(!vals[posarg]) {
  459. sial_error("Expected additional argument %d\n", posarg+1);
  460. } else switch(vals[posarg]->type.type) {
  461. case V_BASE: case V_ENUM:
  462. {
  463. if(!ptrto(M_SIZE)) {
  464. if(vals[posarg]->type.size==8) {
  465. *onefmt++='l';
  466. *onefmt++='l';
  467. }
  468. }
  469. if(sial_issigned(vals[posarg]->type.typattr)) {
  470. *onefmt++='d';
  471. }else{
  472. *onefmt++='u';
  473. }
  474. }
  475. break;
  476. case V_REF:
  477. {
  478. *p='p';
  479. goto ref;
  480. }
  481. case V_STRING:
  482. {
  483. *onefmt++='s';
  484. }
  485. break;
  486. }
  487. p++;
  488. *onefmt='\0';
  489. nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals);
  490. } else {
  491. /* check that format and value_t agree */
  492. /* can't do a lot more then check for strings vs anything_else */
  493. if(!vals[posarg]) {
  494. sial_error("Expected additional argument %d\n", posarg+1);
  495. } else if(*p=='s') {
  496. if(vals[posarg]->type.type != V_STRING) {
  497. sial_error("Expected type 'string' as arg%d", posarg+1);
  498. }
  499. } else if(vals[posarg]->type.type == V_STRING) {
  500. sial_error("Incompatible type 'string' in arg%d", posarg+1);
  501. }
  502. *onefmt++=*p++;
  503. *onefmt='\0';
  504. nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals);
  505. }
  506. } else {
  507. sial_warning("Malformed format specifier!");
  508. }
  509. } else {
  510. last=*p;
  511. if(nfmt-ni > len) sial_error("format tranlation overflow!");
  512. *nfmt++=*p++;
  513. }
  514. }
  515. sial_free(onei);
  516. *nfmt='\0';
  517. return ni;
  518. }
  519. value_t* sial_printf(value_t *vfmt, ...)
  520. {
  521. char *fmt = sial_getptr(vfmt, char);
  522. va_list ap;
  523. value_t *vals[BT_MAXARGS];
  524. int i;
  525. va_start(ap, vfmt);
  526. for(i=0;i<BT_MAXARGS-2;i++){
  527. vals[i]=va_arg(ap,value_t*);
  528. }
  529. va_end(ap);
  530. fmt=sial_ptr(fmt, vals);
  531. fprintf(ofile, "%s", fmt);
  532. sial_free(fmt);
  533. return sial_makebtype(1);
  534. }
  535. #define MAX_SPRINTF 2000
  536. value_t* sial_sprintf(value_t *vfmt, ...)
  537. {
  538. char *fmt=sial_getptr(vfmt, char);
  539. int i;
  540. va_list ap;
  541. value_t *vals[BT_MAXARGS];
  542. value_t *v;
  543. va_start(ap, vfmt);
  544. for(i=0;i<BT_MAXARGS-1;i++){
  545. vals[i]=va_arg(ap,value_t*);
  546. }
  547. va_end(ap);
  548. fmt=sial_ptr(fmt, vals);
  549. v=sial_setstrval(sial_newval(), fmt);
  550. sial_free(fmt);
  551. return v;
  552. }
  553. /*
  554. When there is a parse error in a file.
  555. */
  556. void
  557. sial_error(char *fmt, ...)
  558. {
  559. va_list ap;
  560. sial_setlastfile(filename, sial_line(0));
  561. va_start(ap, fmt);
  562. fprintf(ofile, "File %s, line %d, Error: ", filename, sial_line(0));
  563. vfprintf(ofile, fmt, ap);
  564. fprintf(ofile, "\n");
  565. va_end(ap);
  566. sial_exit(1);
  567. }
  568. void
  569. sial_rerror(srcpos_t *p, char *fmt, ...)
  570. {
  571. va_list ap;
  572. sial_setlastfile(p->file, p->line);
  573. va_start(ap, fmt);
  574. fprintf(ofile, "%s : line %d : Error: ", p->file, p->line);
  575. vfprintf(ofile, fmt, ap);
  576. fprintf(ofile, "\n");
  577. va_end(ap);
  578. sial_exit(1);
  579. }
  580. void
  581. sial_warning(char *fmt, ...)
  582. {
  583. va_list ap;
  584. sial_setlastfile(filename, sial_line(0));
  585. va_start(ap, fmt);
  586. fprintf(ofile, "%s : line %d : Warning: ", filename, lineno);
  587. vfprintf(ofile, fmt, ap);
  588. fprintf(ofile, "\n");
  589. va_end(ap);
  590. }
  591. void
  592. sial_rwarning(srcpos_t *p, char *fmt, ...)
  593. {
  594. va_list ap;
  595. sial_setlastfile(p->file, p->line);
  596. va_start(ap, fmt);
  597. fprintf(ofile, "%s : line %d : Warning: ", p->file, p->line);
  598. vfprintf(ofile, fmt, ap);
  599. fprintf(ofile, "\n");
  600. va_end(ap);
  601. }
  602. void
  603. sial_vilast()
  604. {
  605. if(lastfile) {
  606. sial_exevi(lastfile, lastline);
  607. } else {
  608. sial_msg("No last error record available");
  609. }
  610. }
  611. void
  612. sial_getcomment(void)
  613. {
  614. while(1) {
  615. unsigned char c;
  616. while((c=sial_input())!='*' && c!=255)
  617. if(c==255) goto bad;
  618. if((c=sial_input())=='/') return;
  619. else if(c==255) {
  620. bad:
  621. sial_error("Unterminated comment!");
  622. }
  623. }
  624. }
  625. /* on assignment this function is called to set the new value */
  626. void
  627. sial_setfct(value_t *v1, value_t *v2)
  628. {
  629. /* duplicate type and data, safeguarding array info */
  630. sial_dupval(v1, v2);
  631. /* value_t v1 is still setable */
  632. v1->set=1;
  633. v1->setval=v1;
  634. }
  635. node_t *
  636. sial_sibling(node_t *n, node_t *m)
  637. {
  638. node_t *p;
  639. if(m) {
  640. for(p=n;p->next;p=p->next);
  641. p->next=m;
  642. m->next=0;
  643. }
  644. return n;
  645. }