00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 # include "lclintMacros.nf"
00043 # include "llbasic.h"
00044 # include "osd.h"
00045 # include "herald.h"
00046 # include "lh.h"
00047 # include "llmain.h"
00048
00049
00050 # define TABCH '\1'
00051
00052
00053 # define TABINCH '\2'
00054
00055
00056 # define TABOUTCH '\3'
00057
00058
00059 # define LHTMP_SUFFIX ".lh_tmp"
00060
00061
00062
00063
00064
00065
00066
00067 typedef struct
00068 {
00069 FILE *f;
00070 char *name;
00071 } outFile;
00072
00073 static bool genLh;
00074 static outFile LhFile;
00075 static bool needIncludeBool = FALSE;
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static cstring lhTypeSpecNode (lclTypeSpecNode p_typespec);
00086 static cstring lhTypeExpr ( typeExpr p_x);
00087 static cstring lhDeclaratorNode (declaratorNode p_x);
00088
00089 static FILE *out_open (char *name, char *suffix)
00090 {
00091 char *fullname = (char *)
00092 mstring_create (size_toInt (strlen (name) + strlen (suffix)));
00093 FILE *ret;
00094
00095 strcpy (fullname, name);
00096 strcat (fullname, suffix);
00097 ret = fopen (fullname, "w+");
00098 sfree (fullname);
00099 return ret;
00100 }
00101
00102 cstring
00103 lhFunction (lclTypeSpecNode lclTypeSpec, declaratorNode declarator)
00104 {
00105 cstring s;
00106
00107 if (!genLh)
00108 return cstring_undefined;
00109
00110 s = message ("extern %q\1%q;", lhTypeSpecNode (lclTypeSpec),
00111 lhDeclaratorNode (declarator));
00112
00113 return s;
00114 }
00115
00116 static cstring
00117 lhDeclaratorNode (declaratorNode x)
00118 {
00119 return (lhTypeExpr (x->type));
00120 }
00121
00122 static cstring lhTypeExpr ( typeExpr x)
00123 {
00124 cstring s = cstring_undefined;
00125 paramNodeList params;
00126 int i;
00127
00128 if (x != (typeExpr) 0)
00129 {
00130 cstring front = cstring_undefined;
00131 cstring back = cstring_undefined;
00132
00133 for (i = x->wrapped; i >= 1; i--)
00134 {
00135 front = cstring_appendChar (front, '(');
00136 back = cstring_appendChar (back, ')');
00137 }
00138
00139 switch (x->kind)
00140 {
00141 case TEXPR_BASE:
00142 s = message ("%q%s", s, ltoken_getRawString (x->content.base));
00143 break;
00144 case TEXPR_PTR:
00145 s = message ("%q*%q", s, lhTypeExpr (x->content.pointer));
00146 break;
00147 case TEXPR_ARRAY:
00148 s = message ("%q%q[%q]", s,
00149 lhTypeExpr (x->content.array.elementtype),
00150 termNode_unparse (x->content.array.size));
00151 break;
00152 case TEXPR_FCN:
00153 s = message ("%q%q (", s, lhTypeExpr (x->content.function.returntype));
00154 params = x->content.function.args;
00155
00156 if (!paramNodeList_empty (params))
00157 {
00158 s = message ("%q%q", s,
00159 paramNodeList_unparseComments (x->content.function.args));
00160 }
00161
00162 s = message ("%q)", s);
00163 break;
00164 }
00165 s = message ("%q%q%q", front, s, back);
00166 }
00167 else
00168 {
00169 s = cstring_makeLiteral ("?");
00170 }
00171
00172 return s;
00173 }
00174
00175 extern void
00176 lhForwardStruct (ltoken t)
00177 {
00178 if (!genLh)
00179 return;
00180
00181 lhOutLine (message ("struct %s;", ltoken_unparse (t)));
00182 }
00183
00184
00185 extern void
00186 lhForwardUnion (ltoken t)
00187 {
00188 if (!genLh)
00189 return;
00190
00191 lhOutLine (message ("union %s;", ltoken_unparse (t)));
00192 }
00193
00194 extern cstring
00195 lhType (typeNode t)
00196 {
00197 if (!genLh)
00198 return cstring_undefined;
00199
00200 if (t->kind == TK_EXPOSED)
00201 {
00202 exposedNode n = t->content.exposed;
00203
00204 if (n != (exposedNode) 0)
00205 {
00206 if (declaratorInvNodeList_size (n->decls) == 0)
00207 {
00208
00209
00210
00211
00212 return (cstring_appendChar (lhTypeSpecNode (n->type), ';'));
00213 }
00214 else
00215 {
00216 cstring s = cstring_undefined;
00217
00218 declaratorInvNodeList_elements (n->decls, d)
00219 {
00220 cstring name = declaratorNode_unparse (d->declarator);
00221 cstring pname = declaratorNode_unparseCode (d->declarator);
00222
00223 s = message ("%q\n# ifndef EXPOSED_TYPE_%q\ntypedef %q %q;\n# endif\n",
00224 s, pname, lhTypeSpecNode (n->type), name);
00225 } end_declaratorInvNodeList_elements;
00226
00227 return s;
00228 }
00229 }
00230 }
00231
00232 return cstring_undefined;
00233 }
00234
00235 static cstring
00236 lhTypeSpecNode (lclTypeSpecNode typespec)
00237 {
00238 if (!genLh)
00239 {
00240 return cstring_undefined;
00241 }
00242
00243 return (lclTypeSpecNode_unparseComments (typespec));
00244 }
00245
00246 cstring
00247 lhVarDecl (lclTypeSpecNode lclTypeSpec, initDeclNodeList initDecls,
00248 qualifierKind qualifier)
00249 {
00250 bool first = TRUE;
00251 cstring s;
00252
00253 if (!genLh)
00254 return cstring_undefined;
00255
00256 s = cstring_makeLiteral ("extern");
00257
00258 switch (qualifier)
00259 {
00260 case QLF_NONE:
00261 break;
00262 case QLF_CONST:
00263 s = message ("%q const", s);
00264 break;
00265 case QLF_VOLATILE:
00266 s = message ("%q volatile", s);
00267 break;
00268 default:
00269 break;
00270 }
00271
00272 s = message ("%q %q\1", s, lhTypeSpecNode (lclTypeSpec));
00273
00274 initDeclNodeList_elements (initDecls, i)
00275 {
00276 if (first)
00277 {
00278 s = message ("%q %q", s, declaratorNode_unparse (i->declarator));
00279 first = FALSE;
00280 }
00281 else
00282 {
00283 s = message ("%q, %q", s, declaratorNode_unparse (i->declarator));
00284 }
00285 } end_initDeclNodeList_elements;
00286
00287 return (message ("%q;", s));
00288 }
00289
00290 extern void
00291 lhCleanup (void)
00292
00293 {
00294 if (!genLh)
00295 {
00296 return;
00297 }
00298 else
00299 {
00300 FILE *f;
00301 int c, col = 0, tabcol = 0;
00302 char *fullname;
00303
00304
00305 fullname = mstring_create
00306 (size_toInt (strlen (LhFile.name) + strlen (LHTMP_SUFFIX)));
00307
00308 f = out_open (LhFile.name, LH_SUFFIX);
00309 llassert (LhFile.f != NULL);
00310
00311 strcpy (fullname, LhFile.name);
00312 strcat (fullname, LHTMP_SUFFIX);
00313
00314 if (f == NULL)
00315 {
00316 lldiagmsg (message ("Cannot open lh file for output: %s",
00317 cstring_fromChars (fullname)));
00318 }
00319 else
00320 {
00321 fprintf (f, "/* Output from %s */\n", LCL_PARSE_VERSION);
00322
00323 rewind (LhFile.f);
00324
00325 while (EOF != (c = getc (LhFile.f)))
00326 {
00327 switch (c)
00328 {
00329 case TABCH:
00330 if (col == 0)
00331 {
00332 if (tabcol > 0)
00333 fprintf (f, "%*s", tabcol, "");
00334 }
00335 else
00336 {
00337 check (fputc (' ', f) == (int) ' ');
00338 }
00339 break;
00340
00341 case TABINCH:
00342 tabcol += 4;
00343 break;
00344
00345 case TABOUTCH:
00346 tabcol -= 4;
00347 break;
00348
00349 case '\n':
00350 col = 0;
00351 check (fputc (c, f) == (int) c);
00352 break;
00353
00354 default:
00355 col++;
00356 check (fputc (c, f) == (int) c);
00357 break;
00358 }
00359 }
00360
00361 check (fclose (f) == 0);
00362 check (fclose (LhFile.f) == 0);
00363
00364 (void) osd_unlink (fullname);
00365 LhFile.f = NULL;
00366 }
00367
00368 sfree (fullname);
00369 }
00370 }
00371
00372
00373 extern void
00374 lhIncludeBool (void)
00375 {
00376 needIncludeBool = TRUE;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 void lhInit (tsource * f)
00405 {
00406 static bool lherror = FALSE;
00407
00408 genLh = context_msgLh ();
00409 needIncludeBool = FALSE;
00410
00411 if (!genLh)
00412 {
00413 return;
00414 }
00415
00416 LhFile.name = LSLRootName (tsource_fileName (f));
00417 LhFile.f = out_open (LhFile.name, LHTMP_SUFFIX);
00418
00419 if (LhFile.f == NULL)
00420 {
00421 genLh = FALSE;
00422 if (!lherror)
00423 {
00424 lclplainerror (message ("Cannot write .lh file: %s.lh",
00425 cstring_fromChars (LhFile.name)));
00426 lherror = TRUE;
00427 }
00428 }
00429 }
00430
00431 void lhOutLine ( cstring s)
00432 {
00433 if (genLh)
00434 {
00435 llassert (LhFile.f != NULL);
00436
00437 if (cstring_length (s) > 0)
00438 {
00439 check (fputs (cstring_toCharsSafe (s), LhFile.f) != EOF);
00440 }
00441
00442 check (fputc ('\n', LhFile.f) == (int) '\n');
00443 }
00444
00445 cstring_free (s);
00446 }
00447
00448 void lhExternals (interfaceNodeList x)
00449 {
00450 if (genLh)
00451 {
00452 llassert (LhFile.f != NULL);
00453
00454
00455
00456
00457
00458 interfaceNodeList_elements (x, el)
00459 {
00460 if (el->kind == INF_IMPORTS)
00461 {
00462 importNodeList imps = el->content.imports;
00463
00464 importNodeList_elements (imps, il)
00465 {
00466 if (il->kind == IMPBRACKET)
00467 {
00468 lhOutLine (message ("# include <%s.h>",
00469 ltoken_getRawString (il->val)));
00470 }
00471 } end_importNodeList_elements ;
00472 }
00473 } end_interfaceNodeList_elements;
00474
00475 lhOutLine (cstring_makeLiteral ("# include \"bool.h\""));
00476
00477 interfaceNodeList_elements (x, el)
00478 {
00479 if (el->kind == INF_IMPORTS)
00480 {
00481 importNodeList imps = el->content.imports;
00482
00483 importNodeList_elements (imps, il)
00484 {
00485 if (il->kind != IMPBRACKET)
00486 {
00487 lhOutLine (message ("# include \"%s.h\"",
00488 ltoken_getRawString (il->val)));
00489 }
00490 } end_importNodeList_elements ;
00491 }
00492 } end_interfaceNodeList_elements;
00493
00494 lhOutLine (cstring_undefined);
00495 }
00496 }
00497
00498
00499