wmpager: EWMH support
[dockapps.git] / wmweather+ / subst.c
blob1bbf1390509f9158bde6ae7cfbc3cc58d1e2c0c1
1 #include "config.h"
3 /* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <sys/types.h>
26 #include "die.h"
27 #include "subst.h"
29 #define GROW(var, len){{ \
30 void *c; \
31 len<<=1; \
32 if(len==0) len=1; \
33 if((var=realloc(c=var, len))==NULL){ \
34 out=c; \
35 warn("realloc error"); \
36 goto fail; \
37 } \
40 #define COPY(c) { \
41 if(k>=formatlen) GROW(format, formatlen); \
42 format[k++]=c; \
45 char *subst(const char *s, struct subst_val *substitutes){
46 int i, j, k, n, m;
47 char *out=NULL;
48 size_t outlen=0;
49 char *format=NULL;
50 size_t formatlen=0;
51 int flags;
52 ssize_t str_start;
54 for(i=j=0; s[i]!='\0'; i++){
55 if(s[i]!='%'){
56 if(j>=outlen) GROW(out, outlen);
57 out[j++]=s[i];
58 continue;
60 if(s[i+1]=='%'){
61 if(j>=outlen) GROW(out, outlen);
62 out[j++]=s[i++];
63 continue;
66 n=i;
67 k=0;
68 COPY('%');
70 /* skip flags */
71 flags=0;
72 while(strchr("#0- +'!", s[++n])){
73 if(s[n]=='!'){
74 flags|=1;
75 } else {
76 COPY(s[n]);
80 /* min width? */
81 if(isdigit(s[n]) && s[n]!='0'){
82 COPY(s[n]);
83 while(isdigit(s[++n])){ COPY(s[n]); }
86 /* precision? */
87 if(s[n]=='.'){
88 COPY('.');
89 while(isdigit(s[++n])){ COPY(s[n]); }
92 str_start=0;
93 if(s[n]=='>'){
94 if(s[n+1]=='-'){
95 flags|=2;
96 n++;
98 while(isdigit(s[++n])){
99 str_start=str_start*10+s[n]-'0';
101 if(flags&2) str_start=-str_start;
104 for(m=0; s[n]!=substitutes[m].id && substitutes[m].id!='\0'; m++);
105 if(substitutes[m].id=='\0'){
106 warn("Unknown substitition character '%c' (at %d)\n", s[n], i);
107 goto fail;
110 switch(substitutes[m].type){
111 case HEX:
112 case FLOAT_E:
113 case FLOAT_F:
114 case FLOAT_G:
115 case FLOAT_A:
116 if(flags&1){
117 COPY(toupper(substitutes[m].type));
118 break;
120 /* fall through*/
122 default:
123 COPY(substitutes[m].type);
124 break;
126 COPY('\0');
128 #define PRINT(var) { while((k=j+snprintf(out+j, outlen-j, format, var))>=outlen) GROW(out, outlen); j=k; }
129 switch(substitutes[m].type){
130 case INT:
131 PRINT(*(signed int *)substitutes[m].val);
132 break;
134 case UINT:
135 case OCTAL:
136 case HEX:
137 PRINT(*(unsigned int *)substitutes[m].val);
138 break;
140 case FLOAT_E:
141 case FLOAT_F:
142 case FLOAT_G:
143 case FLOAT_A:
144 PRINT(*(double *)substitutes[m].val);
145 break;
147 case CHAR:
148 PRINT(*(char *)substitutes[m].val);
149 if(flags&1) out[j-1]=toupper(out[j-1]);
150 break;
152 case STRING:
154 char *s=*(char **)substitutes[m].val;
155 if(str_start<0){
156 str_start+=strlen(s);
157 if(str_start<0) str_start=0;
158 } else if(str_start>strlen(s)){
159 s="";
160 str_start=0;
162 s+=str_start;
163 i=j;
164 PRINT(s);
165 if(flags&1){
166 for(; i<j; i++) out[i]=toupper(out[i]);
169 break;
171 default:
172 warn("Unknown substitution type '%c'\n", substitutes[m].type);
173 goto fail;
176 i=n;
179 free(format);
180 if(j>=outlen) GROW(out, outlen);
181 out[j]='\0';
182 return out;
184 fail:
185 free(format);
186 free(out);
187 return NULL;