dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / genmsg / genmsg.l
blob12072628e00b65239fd85468c8767b20b8af3b91
1 %{
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <string.h>
31 #include <libintl.h>
32 #include <locale.h>
33 #include "genmsg.h"
34 #include "y.tab.h"
36 extern int is_cat_found;        /* from main.c */
37 extern void add_comment(Mode, char *);  /* from util.c */
39 int lineno = 1;
42  * msg_line stores the line number where a msgid is to be replaced.
43  */
44 int msg_line = 0;
46 int end_of_cat = TRUE;
49  * In preprocessor mode, genmsg has to parse both the original
50  * soruce code and the code which a preprocessor generates.
51  * While genmsg is parsing the original source code,  'pound_is_mine'
52  * is set to TRUE.
53  */
54 int pound_is_mine = FALSE;
56 void warning(char *);
58 #define NOLINEMSG       -2
60 void set_linemsgid(int, int);
61 int get_linemsgid(int);
64  * cat_field indicates which token is currently parsed by lex.
65  */
66 #define CatdField       0
67 #define SetidField      1
68 #define MsgidField      2
69 #define StrField        3
71 static int cat_field;
74  * This will be turned on when '-' is found in the catgets message
75  * number field.
76  */
77 static int save_minus = FALSE;
79 static char *skip_quoted(int skip_ch);
80 static char *skip_comment(void);
81 static void parse_cppline(char *);
83 %s CAT
86 [0-9a-zA-Z\_\.]catgets  {
87                         if (IsActiveMode(ReplaceMode)) {
88                                 (void) fprintf(newfp, "%s", yytext);
89                         }
90                 }
92 catgets[0-9a-zA-Z\_\.]  {
93                         if (IsActiveMode(ReplaceMode)) {
94                                 (void) fprintf(newfp, "%s", yytext);
95                         }
96                 }
98 catgets         {
99                         if (end_of_cat) {
100                                 /*
101                                  * If the previous catgets
102                                  * state is on, turn it off
103                                  * first.
104                                  */
105                                 BEGIN 0;
106                         }
107                         if (IsActiveMode(ReplaceMode)) {
108                                 (void) fprintf(newfp, "%s", yytext);
109                         }
110                         if (!IsActiveMode(ReplaceMode) ||
111                             !IsActiveMode(PreProcessMode)) {
112                                 BEGIN CAT;
113                                 end_of_cat = FALSE;
114                                 cat_field = CatdField;
115                                 return (CATGETS);
116                         }
117                 }
119 <CAT>\,         {       /* punctuation */
120                         cat_field++;
121                         if (IsActiveMode(ReplaceMode)) {
122                                 (void) fprintf(newfp, "%c", yytext[0]);
123                         }
124                         if (end_of_cat) {
125                                 BEGIN 0;
126                         } else {
127                                 return (yytext[0]);
128                         }
129                 }
131 <CAT>[+*/();>]  {       /* punctuation */
132                         if (IsActiveMode(ReplaceMode)) {
133                                 (void) fprintf(newfp, "%c", yytext[0]);
134                         }
135                         if (end_of_cat) {
136                                 BEGIN 0;
137                         } else {
138                                 return (yytext[0]);
139                         }
140                 }
142 <CAT>const      {
143                         if (IsActiveMode(ReplaceMode)) {
144                                 (void) fprintf(newfp, "%s", yytext);
145                         }
146                         if (end_of_cat) {
147                                 BEGIN 0;
148                         } else {
149                                 return (CONST);
150                         }
151                 }
153 <CAT>nl_catd    {
154                         if (IsActiveMode(ReplaceMode)) {
155                                 (void) fprintf(newfp, "%s", yytext);
156                         }
157                         if (end_of_cat) {
158                                 BEGIN 0;
159                         } else {
160                                 return (CATD);
161                         }
162                 }
164 <CAT>char       {
165                         if (IsActiveMode(ReplaceMode)) {
166                                 (void) fprintf(newfp, "%s", yytext);
167                         }
168                         if (end_of_cat) {
169                                 BEGIN 0;
170                         } else {
171                                 return (CHAR);
172                         }
173                 }
175 <CAT>int        {
176                         if (IsActiveMode(ReplaceMode)) {
177                                 (void) fprintf(newfp, "%s", yytext);
178                         }
179                         if (end_of_cat) {
180                                 BEGIN 0;
181                         } else {
182                                 return (INT);
183                         }
184                 }
186 <CAT>\+\+       {
187                         if (IsActiveMode(ReplaceMode)) {
188                                 (void) fprintf(newfp, "%s", yytext);
189                         }
190                         if (end_of_cat) {
191                                 BEGIN 0;
192                         } else {
193                                 return (INC);
194                         }
195                 }
197 <CAT>\-\-       {
198                         if (IsActiveMode(ReplaceMode)) {
199                                 (void) fprintf(newfp, "%s", yytext);
200                         }
201                         if (end_of_cat) {
202                                 BEGIN 0;
203                         } else {
204                                 return (INC);
205                         }
206                 }
208 <CAT>\"         {       /* extract quoted string */
209                         yylval.str = skip_quoted('"');
210                         if (IsActiveMode(ReplaceMode)) {
211                                 (void) fprintf(newfp, "\"%s\"", yylval.str);
212                         }
213                         if (end_of_cat) { /* just in case */
214                                 BEGIN 0;
215                                 free(yylval.str);
216                         } else {
217                                 return (QSTR);
218                         }
219                 }
221 <CAT>-          {       /* punctuation */
222                         if (IsActiveMode(ReplaceMode)) {
223                                 if (cat_field == MsgidField &&
224                                         get_linemsgid(lineno) != NOLINEMSG) {
225                                         save_minus = TRUE; /*  be replaced. */
226                                 } else {
227                                         (void) fprintf(newfp, "%c", yytext[0]);
228                                 }
229                         }
230                         if (end_of_cat) { /* just in case */
231                                 BEGIN 0;
232                         } else {
233                                 return (yytext[0]);
234                         }
235                 }
237 <CAT>[0-9]+     {       /* numbers */
238                         switch (cat_field) {
239                         case SetidField:
240                                 yylval.id = atoi(yytext);
241                                 if (IsActiveMode(ReplaceMode)) {
242                                         (void) fprintf(newfp, "%s", yytext);
243                                 }
244                                 if (end_of_cat) {
245                                         BEGIN 0;
246                                 } else {
247                                         return (SETID);
248                                 }
249                                 break;
250                         case MsgidField:
251                                 yylval.id = atoi(yytext);
252                                 if (IsActiveMode(ReplaceMode)) {
253                                         int id = get_linemsgid(lineno);
254                                         if (id == NOLINEMSG) {
255                                                 (void) fprintf(newfp, "%s",
256                                                     yytext);
257                                         } else if (id == NOMSGID &&
258                                                 IsActiveMode(ReverseMode)) {
259                                                 (void) fprintf(newfp, "%d",
260                                                     NOMSGID);
261                                         } else if (save_minus == TRUE &&
262                                                 yylval.id == 1) {
263                                                 (void) fprintf(newfp, "%d", id);
264                                         } else { /* just in case */
265                                                 (void) fprintf(newfp, "%s",
266                                                     yytext);
267                                         }
268                                         save_minus = FALSE;
269                                 } else {
270                                         msg_line = lineno;
271                                 }
272                                 if (end_of_cat) {
273                                         BEGIN 0;
274                                 } else {
275                                         return (MSGID);
276                                 }
277                                 break;
278                         default:
279                                 yylval.id = atoi(yytext);
280                                 if (IsActiveMode(ReplaceMode)) {
281                                         (void) fprintf(newfp, "%s", yytext);
282                                 }
283                                 if (end_of_cat) {
284                                         BEGIN 0;
285                                 } else {
286                                         return (DIGIT);
287                                 }
288                         }
289                 }
291 <CAT>[a-zA-Z0-9_\&][a-zA-Z0-9_\>\&\.]*  {
292                         if (IsActiveMode(ReplaceMode)) {
293                                 (void) fprintf(newfp, "%s", yytext);
294                         }
295                         if (end_of_cat) {
296                                 BEGIN 0;
297                         } else {
298                                 return (STR);
299                         }
300                 }
302 <CAT>\n         {
303                         lineno++;
304                         if (IsActiveMode(ReplaceMode)) {
305                                 (void) fprintf(newfp, "\n");
306                         }
307                         if (end_of_cat) {
308                                 BEGIN 0;
309                         }
310                 }
312 <CAT>.          {       /* not interested */
313                         if (IsActiveMode(ReplaceMode)) {
314                                 (void) fprintf(newfp, "%c", yytext[0]);
315                         }
316                         if (end_of_cat) {
317                                 BEGIN 0;
318                         }
319                 }
321 -((([ \t]+)1)|1) {      /* -1 */
322                         if (end_of_cat == FALSE) {
323                                 REJECT
324                         } else if (IsActiveMode(ReplaceMode)) {
325                                 if (IsActiveMode(PreProcessMode)) {
326                                         int id = get_linemsgid(lineno);
327                                         if (id == NOLINEMSG) {
328                                                 (void) fprintf(newfp, "%s",
329                                                     yytext);
330                                         } else { /* could be -1. */
331                                                 (void) fprintf(newfp, "%d", id);
332                                         }
333                                 } else {
334                                         (void) fprintf(newfp, "%s", yytext);
335                                 }
336                         }
337                 }
339 [0-9]+          {
340                         if (IsActiveMode(ReplaceMode)) {
341                                 if (IsActiveMode(PreProcessMode) &&
342                                         IsActiveMode(ReverseMode)) {
343                                         int id = get_linemsgid(lineno);
344                                         if (id == NOLINEMSG) {
345                                                 (void) fprintf(newfp, "%s",
346                                                     yytext);
347                                         } else if (id == NOMSGID) {
348                                                 (void) fprintf(newfp, "%d", id);
349                                         }
350                                 } else {
351                                         (void) fprintf(newfp, "%s", yytext);
352                                 }
353                         }
354                 }
356 ^#[ \t]*[0-9]+.*\n      {       /* pound for c-preprocessor */
357                         if (IsActiveMode(PreProcessMode)) {
358                                 if (IsActiveMode(ReplaceMode)) {
359                                         (void) fprintf(newfp, "%s", yytext);
360                                 } else {
361                                         parse_cppline(yytext);
362                                 }
363                         } else if (IsActiveMode(ReplaceMode)) {
364                                 (void) fprintf(newfp, "%s", yytext);
365                         }
366                         lineno++;
367                 }
369 "/*"            {       /* skip a comment block */
370                         char *comment = skip_comment();
371                         if (IsActiveMode(ReplaceMode)) {
372                                 (void) fprintf(newfp, "%s", comment);
373                         } else {
374                                 if (IsActiveMode(MsgCommentMode)) {
375                                         add_comment(MsgCommentMode, comment);
376                                 }
377                                 if (IsActiveMode(SetCommentMode)) {
378                                         add_comment(SetCommentMode, comment);
379                                 }
380                         }
381                         free(comment);
382                 }
384 "//".*\n        {       /* skip a c++ comment */
385                         if (IsActiveMode(ReplaceMode)) {
386                                 (void) fprintf(newfp, "%s", yytext);
387                         } else {
388                                 if (IsActiveMode(MsgCommentMode)) {
389                                         add_comment(MsgCommentMode, yytext);
390                                 }
391                                 if (IsActiveMode(SetCommentMode)) {
392                                         add_comment(SetCommentMode, yytext);
393                                 }
394                         }
395                         lineno++;
396                 }
398 \"              {       /* skip quoted string */
399                         char *qstr = skip_quoted('"');
400                         if (IsActiveMode(ReplaceMode)) {
401                                 (void) fprintf(newfp, "\"%s\"", qstr);
402                         }
403                         free(qstr);
404                 }
406 \'              {       /* skip single-quoted character */
407                         char *qchr = skip_quoted('\'');
408                         if (IsActiveMode(ReplaceMode)) {
409                                 (void) fprintf(newfp, "\'%s\'", qchr);
410                         }
411                         free(qchr);
412                 }
414 \n              {
415                         if (IsActiveMode(ReplaceMode)) {
416                                 (void) fprintf(newfp, "\n");
417                         }
418                         lineno++;
419                 }
421 .               {
422                         if (IsActiveMode(ReplaceMode)) {
423                                 (void) fprintf(newfp, "%c", yytext[0]);
424                         }
425                 }
429 static char *
430 skip_quoted(int skip_ch)
432         char *buf, *ptr;        /* saved buffer and its pointer */
433         int bsize = BUFSIZ;     /* growing buffer size */
434         int i = 0;              /* counter */
435         int c, old = 0;         /* input character */
437         if ((buf = ptr = malloc(bsize)) == NULL) {
438                 prg_err(gettext("fatal: out of memory"));
439                 exit(EXIT_FAILURE);
440         }
441         for (; ; i++) {
442                 if (i == bsize) {
443                         bsize += BUFSIZ;
444                         if ((buf = realloc(buf, bsize)) == NULL) {
445                                 prg_err(gettext("fatal: out of memory"));
446                                 exit(EXIT_FAILURE);
447                         }
448                         ptr = buf + i;
449                 }
450                 c = input();
451                 if (c == skip_ch && old != '\\') {
452                         break;
453                 } else if (c == '\n') {
454                         lineno++;
455                 } else if (c == 0) {
456                         if (skip_ch == '"') {
457                                 warning(gettext("warning: unmatched \""));
458                         } else if (skip_ch == '\'') {
459                                 warning(gettext("warning: unmatched '"));
460                         } else {
461                                 /* Should not happen */
462                                 warning(gettext(
463                                     "warning: unmatched character"));
464                         }
465                         break;
466                 }
467                 *ptr++ = c;
468                 if (old == '\\') {
469                         old = '\0';
470                 } else {
471                         old = c;
472                 }
473         }
474         *ptr = '\0';
475         return (buf);
478 static char *
479 skip_comment(void)
481         char *buf, *ptr;        /* saved buffer and its pointer */
482         int bsize = BUFSIZ;     /* growing buffer size */
483         int i = 0;              /* counter */
484         int c, old = 0;         /* input character */
486         if ((buf = ptr = malloc(bsize)) == NULL) {
487                 prg_err(gettext("fatal: out of memory"));
488                 exit(EXIT_FAILURE);
489         }
490         *ptr++ = '/';   i++;
491         *ptr++ = '*';   i++;
492         for (; ; i++) {
493                 if (i == bsize) {
494                         bsize += BUFSIZ;
495                         if ((buf = realloc(buf, bsize)) == NULL) {
496                                 prg_err(gettext("fatal: out of memory"));
497                                 exit(EXIT_FAILURE);
498                         }
499                         ptr = buf + i;
500                 }
501                 c = input();
502                 if (c == '/' && old == '*') {
503                         *ptr++ = c;
504                         break;
505                 } else if (c == '\n') {
506                         lineno++;
507                 } else if (c == 0) {
508                         warning(gettext("warning: unmatched /*"));
509                         break;
510                 }
511                 *ptr++ = old = c;
512         }
513         *ptr = '\0';
514         return (buf);
518  * parse_cppline() parses the line control information that a C
519  * preprocessor generates to indicate the location in the original
520  * file.  See the cpp man in the details.
521  */
522 static void
523 parse_cppline(char *str)
525         int n, line, len;
526         char ch;
527         char file[BUFSIZ];
528         char *altfile = NULL;
529         char *pfile;
531         len = strlen(str);
532         if (len >= sizeof (file)) {
533                 if ((altfile = malloc(len + 1)) == NULL) {
534                         prg_err(gettext("fatal: out of memory"));
535                         exit(EXIT_FAILURE);
536                 }
537                 pfile = altfile;
538         } else {
539                 pfile = file;
540         }
541         /* LINTED: E_SEC_SCANF_UNBOUNDED_COPY */
542         n = sscanf(str, "%c%d%s", &ch, &line, pfile);
544         /* 'file' is a quoted string but 'srcfile' is not. */
545         len = strlen(pfile) - 2;
547         pfile++;
548         if (n == 3 && (strncmp(pfile, srcfile, len) == 0)) {
549                 pound_is_mine = TRUE;
550                 lineno = line - 1;
551         } else if (n == 2 && (pound_is_mine == TRUE)) {
552                 lineno = line - 1;
553         } else {
554                 pound_is_mine = FALSE;
555         }
556         if (altfile)
557                 free(altfile);
560 typedef struct {
561         int line;
562         int msgid;
563 } LineMsgID;
565 static LineMsgID line_msgid[NL_MSGMAX];
566 static int line_msgcnt;
568 void
569 init_lex(void)
571         lineno = 1;
572         end_of_cat = TRUE;
573         pound_is_mine = FALSE;
576 void
577 init_linemsgid(void)
579         line_msgcnt = 0;
580         (void) memset(line_msgid, 0, sizeof (LineMsgID) * NL_MSGMAX);
583 void
584 set_linemsgid(int line, int msgid)
586         if (line_msgcnt >= NL_MSGMAX) {
587                 return; /* oops */
588         }
589         line_msgid[line_msgcnt].line = line;
590         line_msgid[line_msgcnt].msgid = msgid;
591         line_msgcnt++;
595 get_linemsgid(int line)
597         int i, left, right;
598         left = 0;
599         right = line_msgcnt - 1;
600         while (left <= right) {
601                 i = (left + right) >> 1;
602                 if (line < line_msgid[i].line) {
603                         right = i - 1;
604                 } else if (line > line_msgid[i].line) {
605                         left = i + 1;
606                 } else {
607                         return (line_msgid[i].msgid);
608                 }
609         }
610         return (NOLINEMSG);
613 void
614 yyerror(char *s)
616         if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) ||
617             IsActiveMode(ReplaceMode)) {
618                 return;
619         }
620         src_err(srcfile, lineno, gettext("%s before or at: %s"), s, yytext);
623 void
624 warning(char *s)
626         if ((IsActiveMode(PreProcessMode) && pound_is_mine == FALSE) ||
627             IsActiveMode(ReplaceMode)) {
628                 return;
629         }
630         src_err(srcfile, lineno, "%s", s);