ViSP
vpLex.cpp
1 /****************************************************************************
2  *
3  * $Id: vpLex.cpp 5310 2015-02-11 11:57:10Z fspindle $
4  *
5 * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  * Description:
34  * Le module "lex.c" contient les procedures de gestion
35  * de l'analyse lexicale de l'analyseur lexicale "lex"
36  * d'un fichier source dont la grammaire possede
37  * les symboles terminaux suivants (ecrit en "LEX", UNIX) :
38  *
39  * Authors:
40  * Jean-Luc CORRE
41  *
42  *****************************************************************************/
43 
44 
45 
46 
47 #include <visp/vpMy.h>
48 #include <visp/vpToken.h>
49 #include <visp/vpKeyword.h>
50 
51 #include <ctype.h>
52 #include <math.h>
53 #include <stdio.h>
54 //#include <unistd.h>
55 #include <fcntl.h>
56 
57 
58 // #include <varargs.h> /* modif pour Fedora */
59 #include <stdarg.h>
60 
61 #include <stdlib.h>
62 #include <string.h>
63 #ifndef DOXYGEN_SHOULD_SKIP_THIS
64 
65 
66 static void count (void);
67 static void next_source (void);
68 
69 void lexerr (const char* path, ...);
70 
71 /* Codes des symboles terminaux */
72 
73 #define NULT 0 /* caractere non valide */
74 #define EOBT 1 /* fin de buffer */
75 #define EOFT 2 /* fin de fichier */
76 #define EOLT 3 /* fin de ligne */
77 #define CMTT 4 /* commentaire */
78 #define IDNT 5 /* identificateur */
79 #define INTT 6 /* nombre entier */
80 #define FPTT 7 /* nombre flottant */
81 #define SGNT 8 /* signe +/- */
82 #define SPCT 9 /* caractere blanc */
83 #define STGT 10 /* caractere de chaine */
84 #define NBRT 11 /* nombre de codes */
85 
86 /* Drapeaux des caracteres */
87 
88 #define _NULT 0x00 /* caractere non valide */
89 #define _CMTT 0x01 /* commentaire */
90 #define _FPTT 0x02 /* nombre flottant */
91 #define _IDNT 0x04 /* identificateur */
92 #define _INTT 0x08 /* nombre entier */
93 #define _SGNT 0x10 /* signe +/- */
94 #define _STGT 0x20 /* caractere de chaine */
95 
96 /* Caracteres sentinelles */
97 
98 #define ASCII_NBR 128 /* nombre de codes ASCII*/
99 
100 #ifndef EOB
101 #define EOB (-2) /* fin de buffer */
102 #endif
103 #ifndef EOF
104 #define EOF (-1) /* fin de fichier */
105 #endif
106 #ifndef EOL
107 #define EOL 10 /* fin de ligne */
108 #endif
109 
110 #define CHAR_NBR 130 /* nombre de caracteres */
111 
112 /* Tests des drapeaux */
113 
114 #define isnult(c) (scantbl[c] == _NULT)
115 #define iscmtt(c) (scantbl[c] & _CMTT)
116 #define isfptt(c) (scantbl[c] & _FPTT)
117 #define isidnt(c) (scantbl[c] & _IDNT)
118 #define isintt(c) (scantbl[c] & _INTT)
119 #define issgnt(c) (scantbl[c] & _SGNT)
120 #define isstgt(c) (scantbl[c] & _STGT)
121 
122 /*
123  * Codes des messages d'erreur de l'analyseur lexicale.
124  */
125 #define E_UNKNOWN 0
126 #define E_SYMBOL 1
127 #define E_CMT_EOF 2
128 #define E_FLOAT 3
129 #define E_INT 4
130 #define E_KEYWORD 5
131 #define E_STG_EOF 6
132 #define E_STG_EOL 7
133 #define E_STRING 8
134 #define E_9 9
135 
136 
137 const char *lex_errtbl[] = { /* table des messages d'erreur */
138  "error unknown",
139  "symbol undefined",
140  "unexpected EOF in comment",
141  "float expected",
142  "int expected",
143  "keyword expected",
144  "unexpected EOF in string or char constant",
145  "newline in string or char constant",
146  "string expected",
147  ""
148 };
149 
150 char *mytext = NULL;
151 int mylength = 0;
152 int mylineno = 1;
153 int mycolumno = 0;
154 float myfloat = 0.0;
155 int myint = 0;
156 
157 
158 static char *mysptr; /* tete de lecture de la ligne courante */
159 static char *myline; /* debut de la ligne courante */
160 static char *lastline; /* derniere ligne du buffer d'entree */
161 
162 static Byte *chtbl; /* premiers caracteres des terminaux */
163 static Byte *scantbl; /* caracteres suivants des terminaux */
164 
165 
166 /*
167  * La procedure "open_lex" alloue et initialise les variables utilisees
168  * par l'analyseur lexical "lex".
169  */
170 void open_lex (void)
171 {
172  static char proc_name[] = "open_lex";
173 
174  int i;
175 
176  if ((chtbl = (Byte *) malloc (CHAR_NBR * sizeof (Byte))) == NULL
177  || (scantbl = (Byte *) malloc (CHAR_NBR * sizeof (Byte))) == NULL) {
178  perror (proc_name);
179  exit (1);
180  }
181  chtbl += 2; /* 2 sentinelles non affichables */
182  scantbl += 2;
183 
184  /* initialise les premiers caracteres des symboles terminaux */
185 
186  for (i = 0; i < ASCII_NBR; i++) {
187  if (isalpha(i)) chtbl[i] = IDNT;
188  else if (isdigit(i)) chtbl[i] = INTT;
189  else if (isspace(i)) chtbl[i] = SPCT;
190  else switch (i) {
191  case '"' : chtbl[i] = STGT; break;
192  case '+' :
193  case '-' : chtbl[i] = SGNT; break;
194  case '.' : chtbl[i] = FPTT; break;
195  case '/' : chtbl[i] = CMTT; break;
196  case '_' : chtbl[i] = IDNT; break;
197  default : chtbl[i] = NULT; break;
198  }
199  }
200 
201  /* Initialise les sentinelles comme des terminaux. */
202 
203  chtbl[EOB] = EOBT;
204  chtbl[EOF] = EOFT;
205  chtbl[EOL] = EOLT;
206 
207  /* Initialise les caracteres suivants des symboles terminaux. */
208 
209  for (i = 0; i < ASCII_NBR; i++) {
210  if (isalpha(i)) scantbl[i] = _CMTT|_IDNT|_STGT;
211  else if (isdigit(i)) scantbl[i] = _CMTT|_IDNT|_INTT|_STGT;
212  else switch (i) {
213  case '"' : scantbl[i] = _CMTT; break;
214  case '+' :
215  case '-' : scantbl[i] = _CMTT|_SGNT|_STGT; break;
216  case '.' : scantbl[i] = _CMTT|_FPTT|_STGT; break;
217  case '/' : scantbl[i] = _STGT; break;
218  case '_' : scantbl[i] = _CMTT|_IDNT|_STGT; break;
219  default : scantbl[i] = _CMTT|_STGT; break;
220  }
221  }
222 
223  /* Initialise les sentinelles comme des terminaux. */
224 
225  scantbl[EOB] = _NULT;
226  scantbl[EOF] = _NULT;
227  scantbl[EOL] = _NULT;
228 }
229 
230 /*
231  * La procedure "close_lex" libere les variables utilisees
232  * par l'analyseur lexical "lex".
233  */
234 void close_lex (void)
235 {
236  free ((char *) (chtbl - 2)); /* voir "open_lex" pour "- 2" */
237  free ((char *) (scantbl - 2));
238 }
239 
240 
241 #define ECHO printf ("%c", *(mysptr))
242 #define CURC (*((signed char *)mysptr)) /* caractere courant */
243 #define NEXTC (*((signed char *)mysptr+1)) /* caractere suivant */
244 #define PREVC (*((signed char *)mysptr-1)) /* caractere precedent */
245 
246 
247 /*
248  * La procedure "lex" contient l'analyseur lexical.
249  * Note :
250  * La tete de lecture (mysptr) n'est pas systematiquement avancee apres lecture.
251  * Le caractere courant est celui sous la tete de lecture.
252  * Ainsi on accede de maniere symetrique aux caracteres precedent et suivant.
253  * Sortie :
254  * Code du symbole terminale analyse.
255  */
256 int lex (void)
257 {
258 lex_loop :
259 
260  for (; chtbl[(int)CURC] == SPCT; mysptr++) {}; /* saute les espaces */
261 
262  switch (chtbl[(int)CURC]) {
263 
264  case NULT :
265  mytext = mysptr; /* sauvegarde le jeton */
266  mysptr++;
267  return (*mytext);
268  break;
269  case EOBT :
270  next_source ();
271  goto lex_loop;
272  break;
273  case EOFT :
274  mytext = mysptr; /* sauvegarde le jeton */
275  return (T_EOF);
276  break;
277  case EOLT :
278  if (mysptr == lastline) next_source ();
279  else mysptr++;
280  mylineno++;
281  myline = mysptr;
282  goto lex_loop;
283  break;
284  case CMTT :
285  mytext = mysptr; /* sauvegarde le jeton */
286  mysptr++;
287  if (CURC != '*')
288  return (*mytext);
289  mysptr++;
290 comment :
291  for (; iscmtt((int)CURC); mysptr++) {};
292  switch (chtbl[(int)CURC]) {
293  case EOBT :
294  next_source ();
295  goto comment;
296  break;
297  case EOFT :
298  lexerr ("start", lex_errtbl[E_CMT_EOF], NULL);
299  return (T_EOF);
300  break;
301  case EOLT :
302  if (mysptr == lastline) next_source ();
303  else mysptr++;
304  mylineno++;
305  myline = mysptr;
306  goto comment;
307  break;
308  case CMTT :
309  if (PREVC == '*') { /* veritable fin */
310  mysptr++;
311  goto lex_loop;
312  }
313  mysptr++; /* pseudo fin */
314  goto comment;
315  break;
316  }
317  break;
318  case IDNT :
319  mytext = mysptr; /* sauvegarde le jeton */
320  mysptr++;
321  for (; isidnt((int)CURC); mysptr++) {};
322  mylength = (int)(mysptr - mytext);
323  return (get_symbol (mytext, mylength));
324  break;
325  case INTT :
326  mytext = mysptr; /* sauvegarde le jeton */
327 int_part :
328  myint = (int) (CURC - '0');
329  mysptr++;
330  for (; isintt((int)CURC); mysptr++)
331  myint = myint * 10 + (int) (CURC - '0');
332  switch (CURC) {
333  case '.' : /* lecture fraction */
334 float_part :
335  mysptr++;
336  for (; isintt((int)CURC); mysptr++) {};
337  if (CURC != 'E' && CURC != 'e') {
338  myfloat = (float) atof (mytext);
339 /* FC
340 printf("mytext %s, myfloat %f\n",mytext,myfloat);
341 */
342  return (T_FLOAT);
343  }
344  break;
345  case 'E' : /* lecture exposant */
346  case 'e' :
347  mysptr++;
348  if (isintt((int)CURC))
349  mysptr++;
350  else if (issgnt((int)CURC) && isintt((int)NEXTC))
351  mysptr +=2;
352  else {
353  mysptr--;
354  myfloat = (float) atof (mytext);
355  return (T_FLOAT);
356  }
357  for (; isintt((int)CURC); mysptr++) {};
358  myfloat = (float) atof (mytext);
359  return (T_FLOAT);
360  break;
361  default :
362  if (*mytext == '-')
363  myint = - myint;
364  return (T_INT);
365  break;
366  }
367  break;
368  case FPTT :
369  mytext = mysptr; /* sauvegarde le jeton */
370  mysptr++;
371  if (! isintt((int)CURC)) /* pas de fraction */
372  return (*mytext);
373  goto float_part;
374  break;
375  case SGNT :
376  mytext = mysptr; /* sauvegarde le jeton */
377  mysptr++;
378  if (isintt((int)CURC))
379  goto int_part;
380  if (isfptt((int)CURC) && isintt((int)NEXTC))
381  goto float_part;
382  return (*mytext);
383  break;
384  case STGT :
385  mytext = mysptr; /* sauvegarde le jeton */
386  mysptr++;
387 string :
388  for (; isstgt((int)CURC); mysptr++) {};
389  switch (chtbl[(int)CURC]) {
390  case EOBT :
391  next_source ();
392  goto string;
393  break;
394  case EOFT :
395  lexerr ("start", lex_errtbl[E_STG_EOF], NULL);
396  return ('\n');
397  break;
398  case EOLT :
399  lexerr ("start", lex_errtbl[E_STG_EOL], NULL);
400  return ('\n');
401  break;
402  case STGT :
403  if (PREVC != '\\') { /* veritable fin */
404  mytext++;
405  mylength = (int)(mysptr - mytext);
406  mysptr++;
407  return (T_STRING);
408  }
409  mysptr++; /* pseudo fin */
410  goto string;
411  break;
412  }
413  break;
414  default :
415  ECHO;
416  mysptr++;
417  goto lex_loop;
418  break;
419  }
420  return (T_EOF);
421 }
422 
423 /*
424  * La procedure "lexecho" contient l'analyseur lexical "lex" :
425  * 1 Analyse le fichier source,
426  * 2 Affiche le fichier source sur le fichier "f",
427  * 3 Stoppe devant le jeton "token".
428  * Note :
429  * La tete de lecture (mysptr) n'est pas systematiquement avancee apres lecture.
430  * Le caractere courant est celui sous la tete de lecture.
431  * Ainsi on accede de maniere symetrique aux caracteres precedent et suivant.
432  * Entree :
433  * f Fichier en sortie.
434  * token Jeton de fin de rechercher.
435  * Sortie :
436  * Code du symbole terminale analyse.
437  */
438 int lexecho (FILE *f, int token)
439 {
440 lex_loop :
441  for (; chtbl[(int)CURC] == SPCT; mysptr++) /* saute les espaces */
442  fwrite (mysptr, 1, 1, f);
443 
444  switch (chtbl[(int)CURC]) {
445 
446  case NULT :
447  mytext = mysptr; /* sauvegarde le jeton */
448  mysptr++;
449  if (token != *mytext)
450  fwrite (mytext, 1, 1, f);
451  return (*mytext);
452  break;
453  case EOBT :
454  next_source ();
455  goto lex_loop;
456  break;
457  case EOFT :
458  mytext = mysptr; /* sauvegarde le jeton */
459  return (T_EOF);
460  break;
461  case EOLT :
462  fwrite (mysptr, 1, 1, f);
463  if (mysptr == lastline) next_source ();
464  else mysptr++;
465  mylineno++;
466  myline = mysptr;
467  goto lex_loop;
468  break;
469  case CMTT :
470  fwrite (mysptr, 1, 1, f);
471  mytext = mysptr; /* sauvegarde le jeton */
472  mysptr++;
473  if (CURC != '*')
474  return (*mytext);
475  fwrite (mysptr, 1, 1, f);
476  mysptr++;
477 comment :
478  for (; iscmtt((int)CURC); mysptr++)
479  fwrite (mysptr, 1, 1, f);
480  switch (chtbl[(int)CURC]) {
481  case EOBT :
482  next_source ();
483  goto comment;
484  break;
485  case EOFT :
486  lexerr ("start", lex_errtbl[E_CMT_EOF], NULL);
487  return (T_EOF);
488  break;
489  case EOLT :
490  fwrite (mysptr, 1, 1, f);
491  if (mysptr == lastline) next_source ();
492  else mysptr++;
493  mylineno++;
494  myline = mysptr;
495  goto comment;
496  break;
497  case CMTT :
498  fwrite (mysptr, 1, 1, f);
499  if (PREVC == '*') { /* veritable fin */
500  mysptr++;
501  goto lex_loop;
502  }
503  mysptr++; /* pseudo fin */
504  goto comment;
505  break;
506  }
507  break;
508  case IDNT :
509  mytext = mysptr; /* sauvegarde le jeton */
510  mysptr++;
511  for (; isidnt((int)CURC); mysptr++) {};
512  mylength = (int)(mysptr - mytext);
513  if (token != get_symbol (mytext, mylength))
514  fwrite (mytext, mylength, 1, f);
515  return (get_symbol (mytext, mylength));
516  break;
517  case INTT :
518  mytext = mysptr; /* sauvegarde le jeton */
519 int_part :
520  mysptr++;
521  for (; isintt((int)CURC); mysptr++) {};
522  switch (CURC) {
523  case '.' : /* lecture fraction */
524 float_part :
525  mysptr++;
526  for (; isintt((int)CURC); mysptr++) {};
527  if (CURC != 'E' && CURC != 'e') {
528  if (token != T_FLOAT)
529  fwrite (mytext, mysptr - mytext, 1, f);
530  return (T_FLOAT);
531  }
532  break;
533  case 'E' : /* lecture exposant */
534  case 'e' :
535  mysptr++;
536  if (isintt((int)CURC)) mysptr++;
537  else if (issgnt((int)CURC) && isintt((int)NEXTC)) mysptr +=2;
538  else {
539  mysptr--;
540  if (token != T_FLOAT)
541  fwrite (mytext, mysptr - mytext, 1, f);
542  return (T_FLOAT);
543  }
544  for (; isintt((int)CURC); mysptr++) {};
545  if (token != T_FLOAT)
546  fwrite (mytext, mysptr - mytext, 1, f);
547  return (T_FLOAT);
548  break;
549  default :
550  if (token != T_INT)
551  fwrite (mytext, mysptr - mytext, 1, f);
552  return (T_INT);
553  break;
554  }
555  break;
556  case FPTT :
557  mytext = mysptr; /* sauvegarde le jeton */
558  mysptr++;
559  if (! isintt((int)CURC)) { /* pas de fraction */
560  if (token != *mytext)
561  fwrite (mytext, 1, 1, f);
562  return (*mytext);
563  }
564  goto float_part;
565  break;
566  case SGNT :
567  mytext = mysptr; /* sauvegarde le jeton */
568  mysptr++;
569  if (isintt((int)CURC)) goto int_part;
570  if (isfptt((int)CURC) && isintt((int)NEXTC)) goto float_part;
571  if (token != *mytext)
572  fwrite (mytext, 1, 1, f);
573  return (*mytext);
574  break;
575  case STGT :
576  fwrite (mysptr, 1, 1, f);
577  mytext = mysptr; /* sauvegarde le jeton */
578  mysptr++;
579 string :
580  for (; isstgt((int)CURC); mysptr++)
581  fwrite (mysptr, 1, 1, f);
582  switch (chtbl[(int)CURC]) {
583  case EOBT :
584  next_source ();
585  goto comment;
586  break;
587  case EOFT :
588  lexerr ("start", lex_errtbl[E_STG_EOF], NULL);
589  return (T_EOF);
590  break;
591  case EOLT :
592  lexerr ("start", lex_errtbl[E_STG_EOL], NULL);
593  return ('\n');
594  break;
595  case STGT :
596  fwrite (mysptr, 1, 1, f);
597  if (PREVC != '\\') { /* veritable fin */
598  mytext++;
599  mylength = (int)(mysptr - mytext);
600  mysptr++;
601  return (T_STRING);
602  }
603  mysptr++; /* pseudo fin */
604  goto string;
605  break;
606  }
607  break;
608  default :
609  fwrite (mysptr, 1, 1, f);
610  mysptr++;
611  goto lex_loop;
612  break;
613  }
614  return (T_EOF);
615 }
616 
617 
618 #undef BUFSIZE
619 #undef LINESIZE
620 #undef TEXTSIZE
621 
622 #define BUFSIZE (BUFSIZ << 5)
623 #define LINESIZE (BUFSIZ-1)
624 #define TEXTSIZE (1 + LINESIZE + BUFSIZE + 1)
625 
626 
627 static FILE *fds; /* descripteur du fichier source */
628 static char *source; /* nom du fichier du programme source */
629 static char *botbuf; /* fond du buffer d'entree du fichier */
630 static char *buf; /* base du buffer d'entree du fichier */
631 static char *topbuf; /* sommet du buffer d'entree du fichier */
632 
633 
634 /*
635  * La procedure "unlex" recule la tete de lecture devant le dernier jeton.
636  */
637 void unlex (void)
638 {
639  mysptr = mytext;
640 }
641 
642 /*
643  * La procedure "open_source" alloue et initialise les variables utilisees
644  * pour la gestion des entrees du programme source.
645  * Entree :
646  * fd Fichier du programme source.
647  * sptr Nom du fichier du programme source.
648  */
649 void open_source (FILE *fd, const char *str)
650 {
651  static char proc_name[] = "open_source";
652 
653  if ((source = (char *) malloc((strlen(str)+1)*sizeof(char))) == NULL) {
654  perror (proc_name);
655  exit (1);
656  }
657  strcpy (source, str);
658  if ((botbuf = (char *) malloc (TEXTSIZE * sizeof (char))) == NULL) {
659  perror (proc_name);
660  exit (1);
661  }
662  fds = fd;
663  buf = botbuf + 1 + LINESIZE;
664  topbuf = buf + 1;
665  mylineno = 1;
666  next_source ();
667 }
668 
669 /*
670  * La procedure "close_source" libere les variables utilisees pour la gestion
671  * des entrees du programme source.
672  */
673 void close_source (void)
674 {
675  free ((char *) source);
676  free ((char *) botbuf);
677 }
678 
679 /*
680  * La procedure "next_source" remplit le buffer courant.
681  */
682 static void next_source (void)
683 {
684  size_t size;
685  char *bot = buf;
686  char *top = topbuf;
687 
688  /* recopie la derniere ligne devant "buf" */
689 
690  *bot = EOL; /* evite le debordement de "buf" */
691  while ((*--bot = *--top) != EOL) {};
692  myline = mysptr = bot + 1;
693 
694  size = fread (buf,sizeof (char), BUFSIZE,fds);
695  if (size == 0) {
696  topbuf = buf + 1;
697  *buf = EOF;
698  *topbuf = EOB; /* sentinelle de fin de fichier */
699  mysptr = buf;
700  }
701  else {
702  topbuf = buf + size;
703  *topbuf = EOB; /* sentinelle de fin de buffer */
704 
705  /* recherche de la derniere ligne */
706  top = topbuf;
707  while (*--top != EOL) {};
708  lastline = top;
709  }
710 }
711 
712 
713 /*
714  * ERR_STACK : Pile des messages d'erreur.
715  * La pile est geree par les procedures "poperr", "popuperr" et "pusherr".
716  * Les messages sont affiches par les procedures "count" et "lexerr".
717  */
718 #define ERR_STACK_MAX 32
719 
720 
721 static const char *err_stack[ERR_STACK_MAX];
722 static int size_stack = 0;
723 
724 
725 /*
726  * La procedure "count" calcule la distance en espaces entre
727  * le premier caractere "*mytext" et le caractere de debut de ligne "*myline".
728  */
729 static void count (void)
730 {
731  char *str;
732 
733  mycolumno = 0;
734  for (str = myline; str <= mytext; str++) {
735  (*str == '\t') ? mycolumno += 8 - (mycolumno % 8u) : mycolumno++;
736  }
737 }
738 
739 /*
740  * La procedure "lexerr" affiche les messages d'erreur.
741  * 1 elle affiche la ligne d'erreur du fichier source.
742  * 2 elle indique la position de l'erreur dans la ligne.
743  * 3 elle affiche les messages d'erreur contenus dans la pile.
744  * 4 elle affiche les messages d'erreur en parametre.
745  * Entree :
746  * va_list Liste de messages d'erreur terminee par NULL.
747  */
748 
749 //lexerr (va_alist)
750 //va_dcl
751 
752 void lexerr (const char* path, ...)
753 {
754  va_list ap;
755  char *cp;
756  int i;
757 
758  /* Pointe sur le caractere fautif. */
759 
760  count ();
761  //write (STDERR, myline, mysptr - myline);
762  fprintf (stderr, "\n%*c\n\"%s\", line %d:\n",
763  mycolumno, '^', source, mylineno);
764 
765  /* Affiche les messages d'erreur de la pile. */
766 
767  for (i = 0; i < size_stack; i++)
768  fprintf (stderr, "%s", err_stack[i]);
769 
770  /* Affiche les messages d'erreur en parametres. */
771 
772  va_start(ap,path);
773  while ((cp = (char *) va_arg(ap, char *)) != NULL)
774  fprintf (stderr, "%s", cp);
775  fprintf (stderr,"\n");
776  va_end(ap);
777 
778  exit (1);
779 }
780 
781 /*
782  * La procedure "poperr" depile le message d'erreur du sommet de pile.
783  */
784 void poperr (void)
785 {
786  static char proc_name[] = "poperr";
787 
788  if (--size_stack < 0) {
789  fprintf (stderr, "%s: error stack underflow\n", proc_name);
790  exit (1);
791  }
792 }
793 
794 /*
795  * La procedure "popup_error" remplace le message d'erreur du sommet de pile.
796  */
797 void popuperr (const char *str)
798 {
799  static const char proc_name[] = "popuerr";
800 
801  if (size_stack <= 0) {
802  fprintf (stderr, "%s: error stack underflow\n", proc_name);
803  exit (1);
804  }
805  err_stack[size_stack-1] = str;
806 }
807 
808 /*
809  * La procedure "pusherr" empile le message d'erreur.
810  */
811 void pusherr (const char *str)
812 {
813  static const char proc_name[] = "pusherr";
814 
815  if (size_stack >= ERR_STACK_MAX) {
816  fprintf (stderr, "%s: error stack overflow\n", proc_name);
817  exit (1);
818  }
819  err_stack[size_stack++] = str;
820 }
821 
822 #endif