/** Parse member function. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi) { stree_fun_t *fun; stree_symbol_t *symbol; bool_t body_expected; fun = stree_fun_new(); symbol = stree_symbol_new(sc_fun); symbol->u.fun = fun; symbol->outer_csi = outer_csi; fun->symbol = symbol; lmatch(parse, lc_fun); fun->name = parse_ident(parse); #ifdef DEBUG_PARSE_TRACE printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid)); #endif fun->sig = parse_fun_sig(parse); /* Parse attributes. */ parse_symbol_attrs(parse, symbol); body_expected = !stree_symbol_has_attr(symbol, sac_builtin) && (outer_csi->cc != csi_interface); fun->proc = stree_proc_new(); fun->proc->outer_symbol = symbol; if (lcur_lc(parse) == lc_scolon) { lskip(parse); /* Body not present */ if (body_expected) { cspan_print(fun->name->cspan); printf(" Error: Function '"); symbol_print_fqn(symbol); printf("' should have a body.\n"); parse_note_error(parse); } fun->proc->body = NULL; } else { lmatch(parse, lc_is); fun->proc->body = parse_block(parse); lmatch(parse, lc_end); /* Body present */ if (!body_expected) { cspan_print(fun->name->cspan); printf(" Error: Function declaration '"); symbol_print_fqn(symbol); printf("' should not have a body.\n"); parse_note_error(parse); } } return fun; }
/** Parse variable declaration statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_vdecl_t *parse_vdecl(parse_t *parse) { stree_vdecl_t *vdecl; vdecl = stree_vdecl_new(); lmatch(parse, lc_var); vdecl->name = parse_ident(parse); lmatch(parse, lc_colon); vdecl->type = parse_texpr(parse); if (lcur_lc(parse) == lc_assign) { lskip(parse); (void) parse_expr(parse); } lmatch(parse, lc_scolon); #ifdef DEBUG_PARSE_TRACE printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid)); printf("vdecl = %p, vdecl->name = %p, sid=%d\n", vdecl, vdecl->name, vdecl->name->sid); #endif return vdecl; }
/** Parse member variable. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi) { stree_var_t *var; stree_symbol_t *symbol; var = stree_var_new(); symbol = stree_symbol_new(sc_var); symbol->u.var = var; symbol->outer_csi = outer_csi; var->symbol = symbol; lmatch(parse, lc_var); var->name = parse_ident(parse); lmatch(parse, lc_colon); var->type = parse_texpr(parse); parse_symbol_attrs(parse, symbol); lmatch(parse, lc_scolon); switch (outer_csi->cc) { case csi_class: case csi_struct: break; case csi_interface: cspan_print(var->name->cspan); printf(" Error: Variable declared inside interface.\n"); parse_note_error(parse); /* XXX Free var */ return NULL; } return var; }
/** Parse member property getter. * * @param parse Parser object. * @param prop Property containing this declaration. */ static void parse_prop_get(parse_t *parse, stree_prop_t *prop) { cspan_t *cspan; stree_block_t *block; stree_proc_t *getter; bool_t body_expected; body_expected = (prop->symbol->outer_csi->cc != csi_interface); lskip(parse); cspan = lprev_span(parse); if (prop->getter != NULL) { cspan_print(cspan); printf(" Error: Duplicate getter.\n"); parse_note_error(parse); return; } if (lcur_lc(parse) == lc_scolon) { /* Body not present */ lskip(parse); block = NULL; if (body_expected) { cspan_print(prop->name->cspan); printf(" Error: Property '"); symbol_print_fqn(prop->symbol); printf("' getter should have " "a body.\n"); parse_note_error(parse); } } else { /* Body present */ lmatch(parse, lc_is); block = parse_block(parse); lmatch(parse, lc_end); if (!body_expected) { cspan_print(prop->name->cspan); printf(" Error: Property '"); symbol_print_fqn(prop->symbol); printf("' getter declaration should " "not have a body.\n"); parse_note_error(parse); /* XXX Free block */ block = NULL; } } /* Create getter procedure */ getter = stree_proc_new(); getter->body = block; getter->outer_symbol = prop->symbol; /* Store getter in property. */ prop->getter = getter; }
/** Parse @c enum declaration. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi) { stree_enum_t *enum_d; stree_symbol_t *symbol; stree_embr_t *embr; enum_d = stree_enum_new(); symbol = stree_symbol_new(sc_enum); symbol->u.enum_d = enum_d; symbol->outer_csi = outer_csi; enum_d->symbol = symbol; lmatch(parse, lc_enum); enum_d->name = parse_ident(parse); list_init(&enum_d->members); #ifdef DEBUG_PARSE_TRACE printf("Parse enum '%s'.\n", strtab_get_str(enum_d->name->sid)); #endif lmatch(parse, lc_is); /* Parse enum members. */ while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) { embr = parse_embr(parse, enum_d); if (embr == NULL) break; list_append(&enum_d->members, embr); } if (list_is_empty(&enum_d->members)) { cspan_print(enum_d->name->cspan); printf("Error: Enum type '%s' has no members.\n", strtab_get_str(enum_d->name->sid)); parse_note_error(parse); } lmatch(parse, lc_end); if (outer_csi != NULL) { switch (outer_csi->cc) { case csi_class: case csi_struct: break; case csi_interface: cspan_print(enum_d->name->cspan); printf(" Error: Enum declared inside interface.\n"); parse_note_error(parse); /* XXX Free enum */ return NULL; } } return enum_d; }
/** Parse @c break statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_break_t *parse_break(parse_t *parse) { stree_break_t *break_s; #ifdef DEBUG_PARSE_TRACE printf("Parse 'break' statement.\n"); #endif break_s = stree_break_new(); lmatch(parse, lc_break); lmatch(parse, lc_scolon); return break_s; }
/** Parse @c raise statement. * * @param parse Parser object. */ static stree_raise_t *parse_raise(parse_t *parse) { stree_raise_t *raise_s; #ifdef DEBUG_PARSE_TRACE printf("Parse 'raise' statement.\n"); #endif raise_s = stree_raise_new(); lmatch(parse, lc_raise); raise_s->expr = parse_expr(parse); lmatch(parse, lc_scolon); return raise_s; }
/** Parse @c switch statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_switch_t *parse_switch(parse_t *parse) { stree_switch_t *switch_s; stree_when_t *when_c; stree_expr_t *expr; #ifdef DEBUG_PARSE_TRACE printf("Parse 'switch' statement.\n"); #endif lmatch(parse, lc_switch); switch_s = stree_switch_new(); list_init(&switch_s->when_clauses); switch_s->expr = parse_expr(parse); lmatch(parse, lc_is); /* Parse @c when clauses. */ while (lcur_lc(parse) == lc_when) { lskip(parse); when_c = stree_when_new(); list_init(&when_c->exprs); while (b_true) { expr = parse_expr(parse); list_append(&when_c->exprs, expr); if (lcur_lc(parse) != lc_comma) break; lskip(parse); } lmatch(parse, lc_do); when_c->block = parse_block(parse); list_append(&switch_s->when_clauses, when_c); } /* Parse @c else clause. */ if (lcur_lc(parse) == lc_else) { lskip(parse); lmatch(parse, lc_do); switch_s->else_block = parse_block(parse); } else { switch_s->else_block = NULL; } lmatch(parse, lc_end); return switch_s; }
/** Parse @c while statement. * * @param parse Parser object. */ static stree_while_t *parse_while(parse_t *parse) { stree_while_t *while_s; #ifdef DEBUG_PARSE_TRACE printf("Parse 'while' statement.\n"); #endif while_s = stree_while_new(); lmatch(parse, lc_while); while_s->cond = parse_expr(parse); lmatch(parse, lc_do); while_s->body = parse_block(parse); lmatch(parse, lc_end); return while_s; }
/** Parse function signature. * * @param parse Parser object. * @return New syntax tree node. */ static stree_fun_sig_t *parse_fun_sig(parse_t *parse) { stree_fun_sig_t *sig; stree_proc_arg_t *arg; sig = stree_fun_sig_new(); lmatch(parse, lc_lparen); #ifdef DEBUG_PARSE_TRACE printf("Parsing function signature.\n"); #endif list_init(&sig->args); if (lcur_lc(parse) != lc_rparen) { /* Parse formal parameters. */ while (!parse_is_error(parse)) { arg = parse_proc_arg(parse); if (stree_arg_has_attr(arg, aac_packed)) { sig->varg = arg; break; } else { list_append(&sig->args, arg); } if (lcur_lc(parse) == lc_rparen) break; lmatch(parse, lc_scolon); } } lmatch(parse, lc_rparen); if (lcur_lc(parse) == lc_colon) { lskip(parse); sig->rtype = parse_texpr(parse); } else { sig->rtype = NULL; } return sig; }
/** Parse @c return statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_return_t *parse_return(parse_t *parse) { stree_return_t *return_s; #ifdef DEBUG_PARSE_TRACE printf("Parse 'return' statement.\n"); #endif return_s = stree_return_new(); lmatch(parse, lc_return); if (lcur_lc(parse) != lc_scolon) return_s->expr = parse_expr(parse); lmatch(parse, lc_scolon); return return_s; }
/* ** Set a group's rotate setting. */ int group_rotate(const char *argv[]) { const char *group = argv[0]; int newstate; if( ! am_administrator() ) return EXIT_DENIED; if(! group || ! argv[1] || ((newstate=gu_torf(argv[1]))==ANSWER_UNKNOWN) ) { fputs(_("You must supply the name of a group and \"true\" or \"false\".\n"), errors); return EXIT_SYNTAX; } /* make sure the group exists */ if(grpopen(group, TRUE, FALSE)) { fprintf(errors, _("The group \"%s\" does not exist.\n"),group); return EXIT_BADDEST; } /* Modify the group's configuration file. */ while(confread()) { if(lmatch(confline, "Rotate:")) break; else conf_printf("%s\n", confline); } conf_printf("Rotate: %s\n", newstate ? "True" : "False"); while(confread()) /* copy rest of file, */ { if(lmatch(confline, "Rotate:")) /* discard */ continue; else /* copy */ conf_printf("%s\n", confline); } confclose(); reread_group(group); /* pprd must know the rotate setting */ return EXIT_OK; } /* end of group_rotate() */
/* Parse @c except clause. * * @param parse Parser object. * @return New syntax tree node. */ static stree_except_t *parse_except(parse_t *parse) { stree_except_t *except_c; #ifdef DEBUG_PARSE_TRACE printf("Parse 'except' statement.\n"); #endif except_c = stree_except_new(); lmatch(parse, lc_except); except_c->evar = parse_ident(parse); lmatch(parse, lc_colon); except_c->etype = parse_texpr(parse); lmatch(parse, lc_do); except_c->block = parse_block(parse); return except_c; }
/** Parse @c if statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_if_t *parse_if(parse_t *parse) { stree_if_t *if_s; stree_if_clause_t *if_c; #ifdef DEBUG_PARSE_TRACE printf("Parse 'if' statement.\n"); #endif if_s = stree_if_new(); list_init(&if_s->if_clauses); /* Parse @c if clause. */ lmatch(parse, lc_if); if_c = stree_if_clause_new(); if_c->cond = parse_expr(parse); lmatch(parse, lc_then); if_c->block = parse_block(parse); list_append(&if_s->if_clauses, if_c); /* Parse @c elif clauses. */ while (lcur_lc(parse) == lc_elif) { lskip(parse); if_c = stree_if_clause_new(); if_c->cond = parse_expr(parse); lmatch(parse, lc_then); if_c->block = parse_block(parse); list_append(&if_s->if_clauses, if_c); } /* Parse @c else clause. */ if (lcur_lc(parse) == lc_else) { lskip(parse); if_s->else_block = parse_block(parse); } else { if_s->else_block = NULL; } lmatch(parse, lc_end); return if_s; }
/** Parse enum member. * * @param parse Parser object. * @param outer_enum Enum containing this declaration. * @return New syntax tree node. In case of parse error, * @c NULL may (but need not) be returned. */ static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum) { stree_embr_t *embr; embr = stree_embr_new(); embr->outer_enum = outer_enum; embr->name = parse_ident(parse); lmatch(parse, lc_scolon); return embr; }
/** Parse delegate. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi) { stree_deleg_t *deleg; stree_symbol_t *symbol; deleg = stree_deleg_new(); symbol = stree_symbol_new(sc_deleg); symbol->u.deleg = deleg; symbol->outer_csi = outer_csi; deleg->symbol = symbol; lmatch(parse, lc_deleg); deleg->name = parse_ident(parse); #ifdef DEBUG_PARSE_TRACE printf("Parsing delegate '%s'.\n", strtab_get_str(deleg->name->sid)); #endif deleg->sig = parse_fun_sig(parse); /* Parse attributes. */ parse_symbol_attrs(parse, symbol); lmatch(parse, lc_scolon); switch (outer_csi->cc) { case csi_class: case csi_struct: break; case csi_interface: cspan_print(deleg->name->cspan); printf(" Error: Delegate declared inside interface.\n"); parse_note_error(parse); /* XXX Free deleg */ return NULL; } return deleg; }
/* Parse expression statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_exps_t *parse_exps(parse_t *parse) { stree_expr_t *expr; stree_exps_t *exps; #ifdef DEBUG_PARSE_TRACE printf("Parse expression statement.\n"); #endif expr = parse_expr(parse); lmatch(parse, lc_scolon); exps = stree_exps_new(); exps->expr = expr; return exps; }
/* ** Set the DefFiltOpts: line for a group. */ int group_deffiltopts_internal(const char *group) { if(grpopen(group, TRUE, FALSE)) { fprintf(errors, "The group \"%s\" does not exist.\n", group); return EXIT_BADDEST; } { void *qobj = NULL; const char *p; gu_Try { qobj = queueinfo_new(QUEUEINFO_GROUP, group); queueinfo_set_warnings_file(qobj, errors); queueinfo_set_debug_level(qobj, debug_level); /* Modify the group's configuration file. */ while(confread()) { if(lmatch(confline, "DefFiltOpts:")) continue; if((p = lmatchp(confline, "Printer:"))) queueinfo_add_printer(qobj, p); conf_printf("%s\n", confline); } if((p = queueinfo_computedDefaultFilterOptions(qobj))) conf_printf("DefFiltOpts: %s\n", p); confclose(); } gu_Final { if(qobj) queueinfo_free(qobj); } gu_Catch { confabort(); fprintf(errors, "%s: %s\n", myname, gu_exception); return exception_to_exitcode(gu_exception_code); } } return EXIT_OK; } /* end of group_deffiltopts_internal() */
/* Parse @c with-except-finally statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_wef_t *parse_wef(parse_t *parse) { stree_wef_t *wef_s; stree_except_t *except_c; #ifdef DEBUG_PARSE_TRACE printf("Parse WEF statement.\n"); #endif wef_s = stree_wef_new(); list_init(&wef_s->except_clauses); if (lcur_lc(parse) == lc_with) { lmatch(parse, lc_with); lmatch(parse, lc_ident); lmatch(parse, lc_colon); (void) parse_texpr(parse); lmatch(parse, lc_assign); (void) parse_expr(parse); } lmatch(parse, lc_do); wef_s->with_block = parse_block(parse); while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) { except_c = parse_except(parse); list_append(&wef_s->except_clauses, except_c); } if (lcur_lc(parse) == lc_finally) { lmatch(parse, lc_finally); lmatch(parse, lc_do); wef_s->finally_block = parse_block(parse); } else { wef_s->finally_block = NULL; } lmatch(parse, lc_end); return wef_s; }
/** Parse formal function argument. * * @param parse Parser object. * @return New syntax tree node. */ static stree_proc_arg_t *parse_proc_arg(parse_t *parse) { stree_proc_arg_t *arg; stree_arg_attr_t *attr; arg = stree_proc_arg_new(); arg->name = parse_ident(parse); lmatch(parse, lc_colon); arg->type = parse_texpr(parse); #ifdef DEBUG_PARSE_TRACE printf("Parse procedure argument.\n"); #endif list_init(&arg->attr); /* Parse attributes. */ while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) { lskip(parse); attr = parse_arg_attr(parse); list_append(&arg->attr, attr); } return arg; }
/** Parse @c for statement. * * @param parse Parser object. * @return New syntax tree node. */ static stree_for_t *parse_for(parse_t *parse) { stree_for_t *for_s; #ifdef DEBUG_PARSE_TRACE printf("Parse 'for' statement.\n"); #endif for_s = stree_for_new(); lmatch(parse, lc_for); lmatch(parse, lc_ident); lmatch(parse, lc_colon); (void) parse_texpr(parse); lmatch(parse, lc_in); (void) parse_expr(parse); lmatch(parse, lc_do); for_s->body = parse_block(parse); lmatch(parse, lc_end); return for_s; }
/* ** Remove a member from a group. This is a separate function because ** it is called from ppad_printer.c when a printer is deleted and ** it is the member of a group. ** ** sucess: EXIT_OK ** bad group: EXIT_BADDEST ** bad member: EXIT_NOTFOUND */ int group_remove_internal(const char *group, const char *member) { char *ptr; int found = FALSE; void *qobj = NULL; if(grpopen(group, TRUE, FALSE)) return EXIT_BADDEST; gu_Try { qobj = queueinfo_new(QUEUEINFO_GROUP, group); queueinfo_set_warnings_file(qobj, errors); queueinfo_set_debug_level(qobj, debug_level); /* ** Copy the configuration file. */ while(confread()) { if(lmatch(confline, "DefFiltOpts:")) /* delete old lines */ continue; if(lmatch(confline, "Printer:")) /* if member name, */ { ptr = &confline[8]; ptr += strspn(ptr, " \t"); if(strcmp(ptr,member)==0) /* If it is the one we */ { /* are deleting, */ found=TRUE; /* set a flag */ continue; /* and don't copy. */ } queueinfo_add_printer(qobj, ptr); /* Otherwise, add its PPD file, */ } conf_printf("%s\n",confline); } /* Emmit the new "DefFiltOpts:" line. */ { const char *cp = queueinfo_computedDefaultFilterOptions(qobj); if(cp) conf_printf("DefFiltOpts: %s\n", cp); } confclose(); } gu_Final { if(qobj) queueinfo_free(qobj); } gu_Catch { confabort(); fprintf(errors, "%s: %s\n", myname, gu_exception); return exception_to_exitcode(gu_exception_code); } if(found) { reread_group(group); return EXIT_OK; } else { return EXIT_NOTFOUND; } } /* end of _group_remove() */
/** Parse member property. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi) { stree_prop_t *prop; stree_symbol_t *symbol; stree_ident_t *ident; stree_proc_arg_t *arg; prop = stree_prop_new(); list_init(&prop->args); symbol = stree_symbol_new(sc_prop); symbol->u.prop = prop; symbol->outer_csi = outer_csi; prop->symbol = symbol; lmatch(parse, lc_prop); if (lcur_lc(parse) == lc_self) { /* Indexed property set */ /* Use some name that is impossible as identifier. */ ident = stree_ident_new(); ident->sid = strtab_get_sid(INDEXER_IDENT); prop->name = ident; lskip(parse); lmatch(parse, lc_lsbr); /* Parse formal parameters. */ while (!parse_is_error(parse)) { arg = parse_proc_arg(parse); if (stree_arg_has_attr(arg, aac_packed)) { prop->varg = arg; break; } else { list_append(&prop->args, arg); } if (lcur_lc(parse) == lc_rsbr) break; lmatch(parse, lc_scolon); } lmatch(parse, lc_rsbr); } else { /* Named property */ prop->name = parse_ident(parse); } lmatch(parse, lc_colon); prop->type = parse_texpr(parse); /* Parse attributes. */ parse_symbol_attrs(parse, symbol); lmatch(parse, lc_is); while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) { switch (lcur_lc(parse)) { case lc_get: parse_prop_get(parse, prop); break; case lc_set: parse_prop_set(parse, prop); break; default: lunexpected_error(parse); } } lmatch(parse, lc_end); return prop; }
/* ** Show a groups members, its rotate setting, and its comment. */ int group_show(const char *argv[]) { const char *function = "group_show"; const char *group = argv[0]; /* The name of the group to show is the argument. */ int x; char *ptr; int rotate = TRUE; /* Is rotate set for this group? */ char *comment = (char*)NULL; /* Group comment. */ int member_count = 0; /* Keep count of members. */ char *members[MAX_GROUPSIZE]; /* The names of the members. */ char *deffiltopts = (char*)NULL; /* The default filter options string. */ char *switchset = (char*)NULL; /* The compressed switchset string. */ char *passthru = (char*)NULL; char *acls = (char*)NULL; #define MAX_ADDONS 32 char *addon[MAX_ADDONS]; int addon_count = 0; if(! group) { fputs(_("You must supply the name of a group to show.\n"), errors); return EXIT_SYNTAX; } if(grpopen(group, FALSE, FALSE)) /* Open the configuration file. */ { fprintf(errors, _("The group \"%s\" does not exist.\n"), group); return EXIT_BADDEST; } while(confread()) /* Read all the lines in the config file. */ { if(lmatch(confline, "Rotate:")) { rotate = gu_torf(&confline[7]); continue; } if(gu_sscanf(confline, "Comment: %A", &ptr) == 1) { if(comment) gu_free(comment); comment = ptr; continue; } if(gu_sscanf(confline, "Printer: %S", &ptr) == 1) { if(member_count < MAX_GROUPSIZE) { members[member_count++] = ptr; } else { fprintf(errors, "%s(): too many members: %s\n", function, ptr); gu_free(ptr); } continue; } if(gu_sscanf(confline, "Switchset: %Z", &ptr) == 1) { if(switchset) gu_free(switchset); switchset = ptr; continue; } if(gu_sscanf(confline, "DefFiltOpts: %Z", &ptr) == 1) { if(deffiltopts) gu_free(deffiltopts); deffiltopts = ptr; continue; } if(gu_sscanf(confline, "PassThru: %Z", &ptr) == 1) { if(passthru) gu_free(passthru); passthru = ptr; continue; } if(gu_sscanf(confline, "ACLs: %Z", &ptr) == 1) { if(acls) gu_free(acls); acls = ptr; continue; } if(confline[0] >= 'a' && confline[0] <= 'z') /* if in addon name space */ { if(addon_count >= MAX_ADDONS) { fprintf(errors, "%s(): addon[] overflow\n", function); } else { addon[addon_count++] = gu_strdup(confline); } continue; } } /* end of line reading while() loop */ confclose(); /* We are done with the configuration file. */ if(!machine_readable) { printf(_("Group name: %s\n"), group); printf(_("Comment: %s\n"), comment ? comment : ""); PUTS(_("Members:")); for(x=0;x<member_count;x++) /* Show what printers are members. */ { if(x==0) printf(" %s", members[x]); else printf(", %s", members[x]); } putchar('\n'); /* End group members line. */ printf(_("Rotate: %s\n"), rotate ? _("True") : _("False")); { const char *s = _("Default Filter Options: "); PUTS(s); if(deffiltopts) print_wrapped(deffiltopts, strlen(s)); putchar('\n'); } PUTS(_("Switchset: ")); if(switchset) print_switchset(switchset); putchar('\n'); /* This rare parameter is shown only when it has a value. */ if(passthru) printf(_("PassThru types: %s\n"), passthru); /* Only displayed if set. */ if(acls) printf(_("ACLs: %s\n"), acls); /* Print the assembed addon settings. */ if(addon_count > 0) { int x; PUTS(_("Addon:")); for(x = 0; x < addon_count; x++) { printf("\t%s\n", addon[x]); gu_free(addon[x]); } } } else { printf("name\t%s\n", group); printf("comment\t%s\n", comment ? comment : ""); PUTS("members\t"); for(x=0; x < member_count; x++) printf("%s%s", x > 0 ? " " : "", members[x]); PUTS("\n"); printf("rotate\t%s\n", rotate ? "yes" : "no"); printf("deffiltopts\t%s\n", deffiltopts ? deffiltopts : ""); PUTS("switchset\t"); if(switchset) print_switchset(switchset); putchar('\n'); printf("passthru\t%s\n", passthru ? passthru : ""); printf("acls\t%s\n", acls ? acls : ""); /* Addon lines */ if(addon_count > 0) { int x; char *p; for(x = 0; x < addon_count; x++) { if((p = strchr(addon[x], ':'))) { *p = '\0'; p++; p += strspn(p, " \t"); printf("addon %s\t%s\n", addon[x], p); } else { printf("addon\t%s\n", addon[x]); } gu_free(addon[x]); } } } if(comment) gu_free(comment); for(x=0;x<member_count;x++) gu_free(members[x]); if(deffiltopts) gu_free(deffiltopts); if(switchset) gu_free(switchset); if(passthru) gu_free(passthru); if(acls) gu_free(acls); return EXIT_OK; } /* end of group_show() */
extern bool walk(Node *n, bool parent) { top: sigchk(); if (n == NULL) { if (!parent) exit(0); set(TRUE); return TRUE; } switch (n->type) { case nArgs: case nBackq: case nConcat: case nCount: case nFlat: case nLappend: case nRedir: case nVar: case nVarsub: case nWord: exec(glob(glom(n)), parent); /* simple command */ break; case nBody: walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); /* WALK doesn't fall through */ case nNowait: { int pid; if ((pid = rc_fork()) == 0) { #if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) setsigdefaults(FALSE); rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ rc_signal(SIGTTIN, SIG_IGN); rc_signal(SIGTSTP, SIG_IGN); setpgid(0, getpid()); #else setsigdefaults(TRUE); /* ignore SIGINT, SIGQUIT, SIGTERM */ #endif mvfd(rc_open("/dev/null", rFrom), 0); walk(n->u[0].p, FALSE); exit(getstatus()); } if (interactive) fprint(2, "%d\n", pid); varassign("apid", word(nprint("%d", pid), NULL), FALSE); redirq = NULL; /* kill pre-redir queue */ break; } case nAndalso: { bool oldcond = cond; cond = TRUE; if (walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nOrelse: { bool oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nBang: set(!walk(n->u[0].p, TRUE)); break; case nIf: { bool oldcond = cond; Node *true_cmd = n->u[1].p, *false_cmd = NULL; if (true_cmd != NULL && true_cmd->type == nElse) { false_cmd = true_cmd->u[1].p; true_cmd = true_cmd->u[0].p; } cond = TRUE; if (!walk(n->u[0].p, TRUE)) true_cmd = false_cmd; /* run the else clause */ cond = oldcond; WALK(true_cmd, parent); } case nWhile: { Jbwrap j; Edata jbreak; Estack e1, e2; bool testtrue, oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */ cond = oldcond; break; } if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); do { Edata block; block.b = newblock(); cond = oldcond; except(eArena, block, &e2); walk(n->u[1].p, TRUE); testtrue = walk(n->u[0].p, TRUE); unexcept(); /* eArena */ cond = TRUE; } while (testtrue); cond = oldcond; unexcept(); /* eBreak */ break; } case nForin: { List *l, *var = glom(n->u[0].p); Jbwrap j; Estack e1, e2; Edata jbreak; if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { Edata block; assign(var, word(l->w, NULL), FALSE); block.b = newblock(); except(eArena, block, &e2); walk(n->u[2].p, TRUE); unexcept(); /* eArena */ } unexcept(); /* eBreak */ break; } case nSubshell: if (dofork(TRUE)) { setsigdefaults(FALSE); walk(n->u[0].p, FALSE); rc_exit(getstatus()); } break; case nAssign: if (n->u[0].p == NULL) rc_error("null variable name"); assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE); set(TRUE); break; case nPipe: dopipe(n); break; case nNewfn: { List *l = glom(n->u[0].p); if (l == NULL) rc_error("null function name"); while (l != NULL) { if (dashex) prettyprint_fn(2, l->w, n->u[1].p); fnassign(l->w, n->u[1].p); l = l->n; } set(TRUE); break; } case nRmfn: { List *l = glom(n->u[0].p); while (l != NULL) { if (dashex) fprint(2, "fn %S\n", l->w); fnrm(l->w); l = l->n; } set(TRUE); break; } case nDup: redirq = NULL; break; /* Null command */ case nMatch: { List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); if (dashex) fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); set(lmatch(a, b)); break; } case nSwitch: { List *v = glom(n->u[0].p); while (1) { do { n = n->u[1].p; if (n == NULL) return istrue(); } while (n->u[0].p == NULL || n->u[0].p->type != nCase); if (lmatch(v, glom(n->u[0].p->u[0].p))) { for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) walk(n->u[0].p, TRUE); break; } } break; } case nPre: { List *v; if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ break; setsigdefaults(FALSE); qredir(n->u[0].p); if (!haspreredir(n->u[1].p)) doredirs(); /* no more preredirs, empty queue */ walk(n->u[1].p, FALSE); rc_exit(getstatus()); /* NOTREACHED */ } else if (n->u[0].p->type == nAssign) { if (isallpre(n->u[1].p)) { walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); } else { Estack e; Edata var; v = glom(n->u[0].p->u[0].p); assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE); var.name = v->w; except(eVarstack, var, &e); walk(n->u[1].p, parent); varrm(v->w, TRUE); unexcept(); /* eVarstack */ } } else panic("unexpected node in preredir section of walk"); break; } case nBrace: if (n->u[1].p == NULL) { WALK(n->u[0].p, parent); } else if (dofork(parent)) { setsigdefaults(FALSE); walk(n->u[1].p, TRUE); /* Do redirections */ redirq = NULL; /* Reset redirection queue */ walk(n->u[0].p, FALSE); /* Do commands */ rc_exit(getstatus()); /* NOTREACHED */ } break; case nEpilog: qredir(n->u[0].p); if (n->u[1].p != NULL) { WALK(n->u[1].p, parent); /* Do more redirections. */ } else { doredirs(); /* Okay, we hit the bottom. */ } break; case nNmpipe: rc_error("named pipes cannot be executed as commands"); /* NOTREACHED */ default: panic("unknown node in walk"); /* NOTREACHED */ } return istrue(); }
/** Parse constructor. * * @param parse Parser object. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi) { stree_ctor_t *ctor; stree_symbol_t *symbol; cspan_t *cspan; ctor = stree_ctor_new(); symbol = stree_symbol_new(sc_ctor); symbol->u.ctor = ctor; symbol->outer_csi = outer_csi; ctor->symbol = symbol; lmatch(parse, lc_new); cspan = lprev_span(parse); /* Fake identifier. */ ctor->name = stree_ident_new(); ctor->name->sid = strtab_get_sid(CTOR_IDENT); ctor->name->cspan = lprev_span(parse); #ifdef DEBUG_PARSE_TRACE printf("Parsing constructor of CSI '"); symbol_print_fqn(csi_to_symbol(outer_csi)); printf("'.\n"); #endif ctor->sig = parse_fun_sig(parse); if (ctor->sig->rtype != NULL) { cspan_print(cspan); printf(" Error: Constructor of CSI '"); symbol_print_fqn(csi_to_symbol(outer_csi)); printf("' has a return type.\n"); parse_note_error(parse); } /* Parse attributes. */ parse_symbol_attrs(parse, symbol); ctor->proc = stree_proc_new(); ctor->proc->outer_symbol = symbol; if (lcur_lc(parse) == lc_scolon) { lskip(parse); /* This constructor has no body. */ cspan_print(cspan); printf(" Error: Constructor of CSI '"); symbol_print_fqn(csi_to_symbol(outer_csi)); printf("' has no body.\n"); parse_note_error(parse); ctor->proc->body = NULL; } else { lmatch(parse, lc_is); ctor->proc->body = parse_block(parse); lmatch(parse, lc_end); } switch (outer_csi->cc) { case csi_class: case csi_struct: break; case csi_interface: cspan_print(ctor->name->cspan); printf(" Error: Constructor declared inside interface.\n"); parse_note_error(parse); /* XXX Free ctor */ return NULL; } return ctor; }
/** Parse class, struct or interface declaration. * * @param parse Parser object. * @param dclass What to parse: @c lc_class, @c lc_struct or @c lc_csi. * @param outer_csi CSI containing this declaration or @c NULL if global. * @return New syntax tree node. */ static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass, stree_csi_t *outer_csi) { stree_csi_t *csi; csi_class_t cc; stree_csimbr_t *csimbr; stree_symbol_t *symbol; stree_ident_t *targ_name; stree_targ_t *targ; stree_texpr_t *pref; switch (dclass) { case lc_class: cc = csi_class; break; case lc_struct: cc = csi_struct; break; case lc_interface: cc = csi_interface; break; default: assert(b_false); } lskip(parse); csi = stree_csi_new(cc); csi->name = parse_ident(parse); list_init(&csi->targ); while (lcur_lc(parse) == lc_slash) { lskip(parse); targ_name = parse_ident(parse); targ = stree_targ_new(); targ->name = targ_name; list_append(&csi->targ, targ); } symbol = stree_symbol_new(sc_csi); symbol->u.csi = csi; symbol->outer_csi = outer_csi; csi->symbol = symbol; #ifdef DEBUG_PARSE_TRACE printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name, strtab_get_str(csi->name->sid)); #endif if (lcur_lc(parse) == lc_colon) { /* Inheritance list */ lskip(parse); while (b_true) { pref = parse_texpr(parse); if (parse_is_error(parse)) break; list_append(&csi->inherit, pref); if (lcur_lc(parse) != lc_plus) break; lskip(parse); } } lmatch(parse, lc_is); list_init(&csi->members); /* Parse class, struct or interface members. */ while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) { csimbr = parse_csimbr(parse, csi); if (csimbr == NULL) continue; list_append(&csi->members, csimbr); } lmatch(parse, lc_end); if (outer_csi != NULL) { switch (outer_csi->cc) { case csi_class: case csi_struct: break; case csi_interface: cspan_print(csi->name->cspan); printf(" Error: CSI declared inside interface.\n"); parse_note_error(parse); /* XXX Free csi */ return NULL; } } return csi; }
/* ** Add a member to a group, creating the group if ** it does not already exist. */ int group_members_add(const char *argv[], gu_boolean do_add) { const char *group = argv[0]; int x; char *ptr; int count = 0; void *qobj = NULL; if( ! am_administrator() ) return EXIT_DENIED; if(do_add) { if(! group || ! argv[1]) { fputs(_("You must specify a new or existing group and one or more printers\n" "to add to it.\n"), errors); return EXIT_SYNTAX; } } else { if(!group) { fputs(_("You must specify a new or existing group and zero or more printers\n" "to be its members.\n"), errors); return EXIT_SYNTAX; } } if(strlen(group) > MAX_DESTNAME) { fputs(_("Group name is too long.\n"), errors); return EXIT_SYNTAX; } if(strpbrk(group, DEST_DISALLOWED)) { fputs(_("Group name contains a disallowed character.\n"), errors); return EXIT_SYNTAX; } if(strchr(DEST_DISALLOWED_LEADING, (int)group[0])) { fputs(_("Group name begins with a disallowed character.\n"), errors); return EXIT_SYNTAX; } /* ** Make sure the proposed new members really exist. ** We do this by trying to open their configuration files ** with prnopen(). */ for(x=1; argv[x]; x++) { if(prnopen(argv[x], FALSE)) { fprintf(errors, _("The printer \"%s\" does not exist.\n"), argv[x]); return EXIT_BADDEST; } else { confclose(); } } /* ** If the group to which we are adding a printer ** does not exist, create it. */ if(grpopen(group, TRUE, TRUE)) return EXIT_INTERNAL; /* Copy up to but not including the 1st "Printer:" line. */ while(confread()) { if(lmatch(confline, "DefFiltOpts:")) /* discard */ continue; if(lmatch(confline, "Printer:")) /* stop */ break; conf_printf("%s\n", confline); /* copy */ } gu_Try { qobj = queueinfo_new(QUEUEINFO_GROUP, group); queueinfo_set_warnings_file(qobj, errors); queueinfo_set_debug_level(qobj, debug_level); /* Copy all the remaining lines. */ do { if((ptr = lmatchp(confline, "Printer:"))) { if(!do_add) /* If we are adding, just delete it. */ continue; for(x=1; argv[x]; x++) /* Is this the same as one we are adding? */ { if(strcmp(ptr, argv[x]) == 0) gu_Throw(_("%d Printer \"%s\" is already a member of \"%s\".\n"), EXIT_ALREADY, argv[x], group); queueinfo_add_printer(qobj, ptr); count++; } } /* Delete old "DefFiltOpts:" lines as we go. */ else if(lmatch(confline, "DefFiltOpts:")) continue; /* Other lines we keep. */ conf_printf("%s\n", confline); } while(confread()); /* Add a "Printer:" line for each new member. */ for(x=1; argv[x]; x++) { conf_printf("Printer: %s\n", argv[x]); queueinfo_add_printer(qobj, argv[x]); count++; } /* Emmit the new "DefFiltOpts:" line. */ { const char *cp = queueinfo_computedDefaultFilterOptions(qobj); if(cp) conf_printf("DefFiltOpts: %s\n", cp); } /* See if adding our printer will make the group too big. */ if(count > MAX_GROUPSIZE) gu_Throw(_("%d Group \"%s\" would have %d members, only %d are allowed.\n"), EXIT_OVERFLOW, group, count, MAX_GROUPSIZE); /* Commit the changes. */ confclose(); } gu_Final { if(qobj) queueinfo_free(qobj); } gu_Catch { confabort(); /* roll back the changes */ fprintf(errors, "%s: %s\n", myname, gu_exception); return exception_to_exitcode(gu_exception_code); } /* necessary because pprd keeps track of mounted media */ reread_group(group); return EXIT_OK; } /* end of group_add() */