Pristine Ack-5.5
[Ack-5.5.git] / util / ceg / as_parser / conversion.c
1 /* This file contains functions to handle %d, %$, %dist constructs in the
2  * as_table.
3  */
4
5
6 pr_text_with_conversions( str)
7 char *str;
8 {
9         char *ptr, *next_conversion(), *pr_conversion();
10
11         while (  ptr = next_conversion( str)) {
12                 /* ptr points to '%'-sign */
13                 *ptr = '\0';
14
15                 out( "fprint( outfile, \"");
16                 out_string( str);
17                 out( "\");");
18
19                 *ptr = '%';
20                 str = pr_conversion( ptr);
21         }
22
23         out( "fprint( outfile, \"");
24         out_string( str);
25         out( "\");");
26 }
27
28
29 out_string( s)
30 char *s;
31 {
32         for ( ; *s != '\0'; s++)
33                 switch ( *s) {
34                   case '"' : out( "\\\"");
35                              break;
36
37                   case '\\': out( "\\\\");
38                              break;
39
40                   case '\n': out( "\\n");
41                              break;
42
43                   default  : out( "%c", *s);
44                 }
45 }
46
47
48 char *next_conversion( str)
49 char *str;
50
51 /* Look for a %-sign, but not in a comment or string! */
52
53 {
54         char *match();
55
56         while ( *str && *str != '%') {
57                 switch ( *str++) {
58                   case '\'' : str = match( '\'', str) + 1;
59                               break;
60                   case '"'  : str = match( '"', str) + 1;
61                               break;
62                 }
63         }
64         return( *str == '%' ? str : (char *)0);
65 }
66
67
68 char *match( c, str)
69 char c, *str;
70
71 /* Look for charcter 'c', but watch out for things like \n */
72
73 {
74         while ( *str && ( *str != c || *(str-1) == '\\'))
75                 str++;
76         return( *str ? str : str-1);
77 }
78
79
80 char *match_bracket( str)
81 char *str;
82
83 /* find ')', but look at nesting '('-')' pairs, return position of ')'.
84  * Skip strings and comments.
85  */
86 {
87         int depth;
88         char *match();
89
90         depth = 1;
91         while ( *str && depth != 0) { 
92                 switch ( *str++) {
93                   case '\'' : str = match( '\'', str+1) + 1;
94                               break;
95                   case '"'  : str = match( '"', str+1) + 1;
96                               break;
97                   case '('  : depth++;
98                               break;
99                   case ')'  : depth--;
100                               break;
101                 }
102         }
103         return( str-1);
104 }
105
106
107 char *find( c, str)
108 char c, *str;
109 {
110         while ( *str && *str != c)
111                 str++;
112         return( str);
113 }
114         
115 char *pr_conversion( str)
116 char *str;
117
118 /* str points to '%'-sign, returns pointer to first character AFTER the
119  * conversion. %$ will result in a call of eval(), %d will call dist().
120  */
121 {
122         char *start, *ptr, *match_bracket(), *find();
123
124         start = find( '(', str+1);
125         *start++ = '\0';
126
127         ptr = match_bracket( start);
128         *ptr = '\0';
129
130         if ( *(str+1) == '$')
131                 out( "eval( %s);", start);
132         else if ( strncmp( str+1, "dist", 4) == 0)
133                 out( "dist( %s);", start);
134         else
135                 out( "fprint( outfile, \"%%%s\", %s);", str+1, start);
136
137         return( ptr+1);
138 }